00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "type.h"
00036 #include "str.h"
00037 #include <alloc.h>
00038
00039 #include <assert.h>
00040 #include <apr_pools.h>
00041 #include <apr_strings.h>
00042 #include <stdarg.h>
00043 #include <stdlib.h>
00044 #include <errno.h>
00045
00046
00047 bs_data_type *new_bs_data_type(apr_pool_t *mp, const char *name)
00048 {
00049 bs_data_type *ret = apr_pcalloc(mp, sizeof(bs_data_type));
00050 if (!ret) return NULL;
00051
00052 ret->name = apr_pstrdup(mp, name);
00053 ret->builtin = is_builtin_type(name);
00054 ret->from_mp = TRUE;
00055 return ret;
00056 }
00057
00058
00059 bs_message *new_bs_message(apr_pool_t *mp, const char *name, bs_uint16 num_parts)
00060 {
00061 bs_message *ret = apr_pcalloc(mp, sizeof(bs_message));
00062 if (!ret) return NULL;
00063
00064 ret->name = apr_pstrdup(mp, name);
00065 ret->from_mp = TRUE;
00066 if (num_parts > 0) {
00067 ret->num_parts = num_parts;
00068 ret->parts = (bs_message_part **) apr_pcalloc(mp,
00069 sizeof(bs_message_part *) * num_parts);
00070 }
00071 return ret;
00072 }
00073
00074
00075 inline void add_part_to_message(bs_message *msg, bs_message_part *part, apr_pool_t *mp)
00076 {
00077 int orig_size;
00078 assert(msg && part);
00079
00080 orig_size = msg->num_parts * sizeof(bs_message_part *);
00081 msg->parts = pool_realloc(msg->parts, orig_size,
00082 orig_size + sizeof(bs_message_part *), mp);
00083 msg->parts[msg->num_parts++] = part;
00084 }
00085
00086
00087 bs_message_part *new_bs_message_part(apr_pool_t *mp, const char *name,
00088 bs_data_type *type)
00089 {
00090 bs_message_part *ret = apr_pcalloc(mp, sizeof(bs_message_part));
00091 if (!ret) return NULL;
00092
00093 ret->name = apr_pstrdup(mp, name);
00094 ret->type = type;
00095 ret->from_mp = TRUE;
00096 return ret;
00097 }
00098
00099
00100 bs_operation *new_bs_operation(apr_pool_t *mp, const char *name,
00101 bs_message *input, bs_message *output, bs_message *fault)
00102 {
00103 bs_operation *ret = apr_pcalloc(mp, sizeof(bs_operation));
00104 if (!ret) return NULL;
00105
00106 ret->name = apr_pstrdup(mp, name);
00107 ret->input = input;
00108 ret->output = output;
00109 ret->fault = fault;
00110 ret->from_mp = TRUE;
00111 return ret;
00112 }
00113
00114
00115 bs_port_type *new_bs_port_type(apr_pool_t *mp, const char *name,
00116 bs_uint16 num_operations)
00117 {
00118 bs_port_type *ret = apr_pcalloc(mp, sizeof(bs_port_type));
00119 if (!ret) return NULL;
00120
00121 ret->name = apr_pstrdup(mp, name);
00122 ret->from_mp = TRUE;
00123 if (num_operations > 0) {
00124 ret->num_operations = num_operations;
00125 ret->operations = (bs_operation **) apr_pcalloc(mp,
00126 sizeof(bs_operation *) * num_operations);
00127 }
00128 return ret;
00129 }
00130
00131
00132 inline void add_operation_to_port_type(bs_port_type *pt, bs_operation *op,
00133 apr_pool_t *mp)
00134 {
00135 int orig_size;
00136 assert(pt && op);
00137
00138 orig_size = pt->num_operations * sizeof(bs_operation *);
00139 pt->operations = pool_realloc(pt->operations, orig_size,
00140 orig_size + sizeof(bs_operation *), mp);
00141 pt->operations[pt->num_operations++] = op;
00142 }
00143
00144
00145 bs_port *new_bs_port(apr_pool_t *mp, const char *name, bs_port_type *type)
00146 {
00147 bs_port *ret = apr_pcalloc(mp, sizeof(bs_port));
00148 if (!ret) return NULL;
00149
00150 ret->name = apr_pstrdup(mp, name);
00151 ret->port_type = type;
00152 ret->from_mp = TRUE;
00153 return ret;
00154 }
00155
00156
00157 bs_service *new_bs_service(apr_pool_t *mp, const char *name,
00158 bs_uint16 num_ports)
00159 {
00160 bs_service *ret = apr_pcalloc(mp, sizeof(bs_service));
00161 if (!ret) return NULL;
00162
00163 ret->name = apr_pstrdup(mp, name);
00164 ret->from_mp = TRUE;
00165 if (num_ports > 0) {
00166 ret->num_ports = num_ports;
00167 ret->ports = (bs_port **) apr_pcalloc(mp,
00168 sizeof(bs_port *) * num_ports);
00169 }
00170 return ret;
00171 }
00172
00173
00174 inline void add_port_to_service(bs_service *svc, bs_port *port,
00175 apr_pool_t *mp)
00176 {
00177 int orig_size;
00178 assert(svc && port);
00179
00180 orig_size = svc->num_ports * sizeof(bs_port *);
00181 svc->ports = pool_realloc(svc->ports, orig_size,
00182 orig_size + sizeof(bs_port *), mp);
00183 svc->ports[svc->num_ports++] = port;
00184 }
00185
00186
00187 bs_definition *new_bs_definition(apr_pool_t *mp, const char *name,
00188 bs_uint16 num_data_types, bs_uint16 num_messages,
00189 bs_uint16 num_port_types, bs_uint16 num_services)
00190 {
00191 bs_definition *ret = apr_pcalloc(mp, sizeof(bs_definition));
00192 if (!ret) return NULL;
00193
00194 ret->name = apr_pstrdup(mp, name);
00195 ret->from_mp = TRUE;
00196 if (num_data_types > 0) {
00197 ret->num_data_types = num_data_types;
00198 ret->data_types = (bs_data_type **) apr_pcalloc(mp,
00199 sizeof(bs_data_type *) * num_data_types);
00200 }
00201 if (num_messages > 0) {
00202 ret->num_messages = num_messages;
00203 ret->messages = (bs_message **) apr_pcalloc(mp,
00204 sizeof(bs_message *) * num_messages);
00205 }
00206 if (num_port_types > 0) {
00207 ret->num_port_types = num_port_types;
00208 ret->port_types = (bs_port_type **) apr_pcalloc(mp,
00209 sizeof(bs_port_type *) * num_port_types);
00210 }
00211 if (num_services > 0) {
00212 ret->num_services = num_services;
00213 ret->services = (bs_service **) apr_pcalloc(mp,
00214 sizeof(bs_service *) * num_services);
00215 }
00216 return ret;
00217 }
00218
00219
00220 inline void add_data_type_to_definition(bs_definition *def, bs_data_type *type,
00221 apr_pool_t *mp)
00222 {
00223 int orig_size;
00224 bs_uint16 i;
00225 assert(def && type);
00226
00227
00228 for (i = 0; i < def->num_data_types; i++) {
00229 bs_data_type *t = def->data_types[i];
00230 if (streq(type->name, t->name)) return;
00231 }
00232
00233
00234 orig_size = def->num_data_types * sizeof(bs_data_type *);
00235 def->data_types = pool_realloc(def->data_types, orig_size,
00236 orig_size + sizeof(bs_data_type *), mp);
00237 def->data_types[def->num_data_types++] = type;
00238 }
00239
00240
00241 inline void add_message_to_definition(bs_definition *def, bs_message *msg,
00242 apr_pool_t *mp)
00243 {
00244 int orig_size;
00245 bs_uint16 i;
00246 assert(def && msg);
00247
00248
00249 for (i = 0; i < def->num_messages; i++) {
00250 bs_message *m = def->messages[i];
00251 if (streq(msg->name, m->name)) return;
00252 }
00253
00254
00255 orig_size = def->num_messages * sizeof(bs_message *);
00256 def->messages = pool_realloc(def->messages, orig_size,
00257 orig_size + sizeof(bs_message *), mp);
00258 def->messages[def->num_messages++] = msg;
00259 }
00260
00261
00262 inline void add_port_type_to_definition(bs_definition *def, bs_port_type *pt,
00263 apr_pool_t *mp)
00264 {
00265 int orig_size;
00266 bs_uint16 i;
00267 assert(def && pt);
00268
00269
00270 for (i = 0; i < def->num_port_types; i++) {
00271 bs_port_type *p = def->port_types[i];
00272 if (streq(pt->name, p->name)) return;
00273 }
00274
00275
00276 orig_size = def->num_port_types * sizeof(bs_port_type *);
00277 def->port_types = pool_realloc(def->port_types, orig_size,
00278 orig_size + sizeof(bs_port_type *), mp);
00279 def->port_types[def->num_port_types++] = pt;
00280 }
00281
00282
00283 inline void add_service_to_definition(bs_definition *def, bs_service *svc,
00284 apr_pool_t *mp)
00285 {
00286 int orig_size;
00287 bs_uint16 i;
00288 assert(def && svc);
00289
00290
00291 for (i = 0; i < def->num_services; i++) {
00292 bs_service *s = def->services[i];
00293 if (streq(svc->name, s->name)) return;
00294 }
00295
00296
00297 orig_size = def->num_services * sizeof(bs_service *);
00298 def->services = pool_realloc(def->services, orig_size,
00299 orig_size + sizeof(bs_service *), mp);
00300 def->services[def->num_services++] = svc;
00301 }
00302
00303
00304 bs_service_request *new_bs_service_request(apr_pool_t *mp, bs_byte *uuid,
00305 char *service, char *port, char *operation,
00306 bs_message_instance *input)
00307 {
00308 unsigned i;
00309 bs_service_request *req;
00310
00311 req = apr_pcalloc(mp, sizeof(bs_service_request));
00312 for (i = 0; i < 16; i++) req->uuid[i] = uuid[i];
00313
00314 if (service) req->service = apr_pstrdup(mp, service);
00315 if (port) req->port = apr_pstrdup(mp, port);
00316 if (operation) req->operation = apr_pstrdup(mp, operation);
00317 req->input = input;
00318 req->from_mp = TRUE;
00319 return req;
00320 }
00321
00322
00323 bs_service_response *new_bs_service_response(apr_pool_t *mp,
00324 const bs_byte *uuid,
00325 const char *service, const char *port, const char *operation,
00326 bs_message_instance *output, bs_message_instance *fault)
00327 {
00328 unsigned i;
00329 bs_service_response *resp;
00330
00331 resp = apr_pcalloc(mp, sizeof(bs_service_response));
00332 for (i = 0; i < 16; i++) resp->uuid[i] = uuid[i];
00333 resp->service = apr_pstrdup(mp, service);
00334 resp->port = apr_pstrdup(mp, port);
00335 resp->operation = apr_pstrdup(mp, operation);
00336 resp->output = output;
00337 resp->fault = fault;
00338 resp->from_mp = TRUE;
00339 return resp;
00340 }
00341
00342
00343 bs_message_instance *new_bs_message_instance(apr_pool_t *mp, const char *name,
00344 const bs_uint16 num_parts)
00345 {
00346 bs_message_instance *ret;
00347
00348 ret = apr_pcalloc(mp, sizeof(bs_message_instance));
00349 ret->name = apr_pstrdup(mp, name);
00350 if (num_parts > 0) {
00351 ret->num_parts = num_parts;
00352 ret->parts = apr_pcalloc(mp, num_parts * sizeof(bs_part_instance *));
00353 }
00354 ret->from_mp = TRUE;
00355 return ret;
00356 }
00357
00358
00359 bs_part_instance *new_bs_part_instance(apr_pool_t *mp, const char *name,
00360 bs_data_type *type, const char *data, bs_uint64 size)
00361 {
00362 bs_part_instance *ret;
00363 ret = apr_pcalloc(mp, sizeof(bs_part_instance));
00364 ret->name = apr_pstrdup(mp, name);
00365 ret->type = type;
00366 ret->data = apr_pstrndup(mp, data, size);
00367 ret->size = size;
00368 ret->from_mp = TRUE;
00369 return ret;
00370 }
00371
00372
00373 inline void add_part_to_request_instance(bs_part_instance *part,
00374 bs_message_instance *msg, apr_pool_t *mp)
00375 {
00376 bs_uint16 orig_size;
00377 assert(msg && part);
00378
00379 orig_size = msg->num_parts * sizeof(bs_part_instance *);
00380 msg->parts = pool_realloc(msg->parts, orig_size,
00381 orig_size + sizeof(bs_part_instance *), mp);
00382 msg->parts[msg->num_parts++] = part;
00383 }
00384
00385
00386 bs_status merge_def_with_def(apr_pool_t *mp, bs_definition *result,
00387 bs_definition *d)
00388 {
00389 bs_uint16 i;
00390
00391 for (i = 0; i < d->num_data_types; i++)
00392 add_data_type_to_definition(result, d->data_types[i], mp);
00393
00394 for (i = 0; i < d->num_messages; i++)
00395 add_message_to_definition(result, d->messages[i], mp);
00396
00397 for (i = 0; i < d->num_port_types; i++)
00398 add_port_type_to_definition(result, d->port_types[i], mp);
00399
00400 for (i = 0; i < d->num_services; i++)
00401 add_service_to_definition(result, d->services[i], mp);
00402
00403 return BS_OK;
00404 }
00405
00406
00407 bs_status merge_bs_definitions(apr_pool_t *mp, bs_definition **def, ...)
00408 {
00409 va_list argptr;
00410 bs_definition *d, *result;
00411
00412 result = new_bs_definition(mp, "service_definitions", 0, 0, 0, 0);
00413
00414 va_start(argptr, def);
00415 while ((d = va_arg(argptr, bs_definition *)) != NULL) {
00416 bs_status rv = merge_def_with_def(mp, result, d);
00417 if (rv != BS_OK) {
00418 va_end(argptr);
00419 return BS_ERROR;
00420 }
00421 }
00422 va_end(argptr);
00423
00424 *def = result;
00425 return BS_OK;
00426 }
00427
00428
00429 bs_bool is_builtin_type(const char *name)
00430 {
00431 if (streq(name, "bs_bool")) return TRUE;
00432 else if (streq(name, "bs_string")) return TRUE;
00433 else if (streq(name, "bs_byte")) return TRUE;
00434 else if (streq(name, "bs_int16")) return TRUE;
00435 else if (streq(name, "bs_uint16")) return TRUE;
00436 else if (streq(name, "bs_int32")) return TRUE;
00437 else if (streq(name, "bs_uint32")) return TRUE;
00438 else if (streq(name, "bs_int64")) return TRUE;
00439 else if (streq(name, "bs_uint64")) return TRUE;
00440 else if (streq(name, "bs_double")) return TRUE;
00441 else return FALSE;
00442 }
00443
00444
00450 static inline bs_status check_builtin_type_bs_bool(bs_part_instance *inst)
00451 {
00452
00453 if (apr_strnatcasecmp(inst->data, "true") == 0) return BS_OK;
00454 else if (apr_strnatcasecmp(inst->data, "false") == 0) return BS_OK;
00455 if (apr_strnatcasecmp(inst->data, "1") == 0) return BS_OK;
00456 else if (apr_strnatcasecmp(inst->data, "0") == 0) return BS_OK;
00457 else return BS_TYPE_NO_BOOLEAN;
00458 }
00459
00460
00468 static inline bs_status check_builtin_type_bs_string(bs_part_instance *inst)
00469 {
00470
00471 if (inst->data[inst->size] != '\0') return BS_TYPE_STRING_NO_TERM;
00472 return BS_OK;
00473 }
00474
00475
00481 static inline bs_status check_builtin_type_bs_byte(bs_part_instance *inst)
00482 {
00483
00484 if (inst->size != 1) return BS_TYPE_BYTE_ERROR;
00485 return BS_OK;
00486 }
00487
00488
00494 static inline bs_status check_builtin_type_bs_int16(bs_part_instance *inst)
00495 {
00496 apr_int64_t num;
00497 char *end;
00498
00499
00500 if (inst->size > 6) return BS_ERROR;
00501 num = apr_strtoi64(inst->data, &end, 0);
00502 if (num > 32767 || num < -32767) return BS_ERROR;
00503 return BS_OK;
00504 }
00505
00506
00513 static inline bs_status check_builtin_type_bs_uint16(bs_part_instance *inst)
00514 {
00515 apr_int64_t num;
00516 char *end;
00517
00518
00519 if (inst->size > 6) return BS_ERROR;
00520 num = apr_strtoi64(inst->data, &end, 0);
00521 if (num > 65535) return BS_ERROR;
00522 return BS_OK;
00523 }
00524
00525
00531 static inline bs_status check_builtin_type_bs_int32(bs_part_instance *inst)
00532 {
00533 apr_int64_t num;
00534 char *end;
00535
00536
00537 if (inst->size > 11) return BS_ERROR;
00538 num = apr_strtoi64(inst->data, &end, 0);
00539 if (num > 2147483647 || num < -2147483647) return BS_ERROR;
00540 return BS_OK;
00541 }
00542
00543
00550 static inline bs_status check_builtin_type_bs_uint32(bs_part_instance *inst)
00551 {
00552 apr_int64_t num;
00553 char *end;
00554
00555
00556 if (inst->size > 11) return BS_ERROR;
00557 num = apr_strtoi64(inst->data, &end, 0);
00558 if (num > 0xffffffff) return BS_ERROR;
00559 return BS_OK;
00560 }
00561
00562
00568 static inline bs_status check_builtin_type_bs_int64(bs_part_instance *inst)
00569 {
00570 bs_int64 num;
00571 char *end;
00572
00573 num = apr_strtoi64(inst->data, &end, 0);
00574 if (errno == ERANGE) return BS_TYPE_RANGE;
00575 return BS_OK;
00576 }
00577
00578
00585 static inline bs_status check_builtin_type_bs_uint64(bs_part_instance *inst)
00586 {
00587 bs_int64 num;
00588 char *end;
00589
00590 num = apr_strtoi64(inst->data, &end, 0);
00591 if (errno == ERANGE) return BS_TYPE_RANGE;
00592 if (num < 0) return BS_TYPE_RANGE;
00593 return BS_OK;
00594 }
00595
00596
00603 static inline bs_status check_builtin_type_bs_double(bs_part_instance *inst)
00604 {
00605 bs_double num;
00606 char *end;
00607
00608 if (inst->size > 15) return BS_TYPE_CONVERT_ERROR;
00609
00610 num = strtod(inst->data, &end);
00611 if (errno == EINVAL) return BS_TYPE_CONVERT_ERROR;
00612 if (errno == ERANGE) return BS_TYPE_RANGE;
00613 return BS_OK;
00614 }
00615
00616
00617 bs_status check_builtin_type(bs_part_instance *inst)
00618 {
00619 bs_data_type *type = inst->type;
00620
00621 if (streq(type->name, "bs_bool"))
00622 return check_builtin_type_bs_bool(inst);
00623 else if (streq(type->name, "bs_string"))
00624 return check_builtin_type_bs_string(inst);
00625 else if (streq(type->name, "bs_byte"))
00626 return check_builtin_type_bs_byte(inst);
00627 else if (streq(type->name, "bs_int16"))
00628 return check_builtin_type_bs_int16(inst);
00629 else if (streq(type->name, "bs_uint16"))
00630 return check_builtin_type_bs_uint16(inst);
00631 else if (streq(type->name, "bs_int32"))
00632 return check_builtin_type_bs_int32(inst);
00633 else if (streq(type->name, "bs_uint32"))
00634 return check_builtin_type_bs_uint32(inst);
00635 else if (streq(type->name, "bs_int64"))
00636 return check_builtin_type_bs_int64(inst);
00637 else if (streq(type->name, "bs_uint64"))
00638 return check_builtin_type_bs_uint64(inst);
00639 else if (streq(type->name, "bs_double"))
00640 return check_builtin_type_bs_double(inst);
00641 else
00642 return BS_ERROR;
00643 }
00644
00645
00653 static bs_bool compare_message_parts(const bs_part_instance *inst,
00654 bs_message_part *def)
00655 {
00656 if (!streq(inst->name, def->name)) return FALSE;
00657 if (!streq(inst->type->name, def->type->name)) return FALSE;
00658 return TRUE;
00659 }
00660
00661
00670 static bs_bool can_service_parts(const bs_service_request *request,
00671 const bs_operation *operation)
00672 {
00673 unsigned i;
00674
00675
00676 if (request->input->num_parts != operation->input->num_parts)
00677 return FALSE;
00678
00679
00680 for (i = 0; i < request->input->num_parts; i++) {
00681 if (!compare_message_parts(request->input->parts[i],
00682 operation->input->parts[i])) return FALSE;
00683 }
00684 return TRUE;
00685 }
00686
00687
00697 static bs_bool can_service(const bs_service_request *request,
00698 const bs_definition *def)
00699 {
00700 unsigned i;
00701 bs_service *svc = NULL;
00702 bs_port_type *pt = NULL;
00703
00704
00705 for (i = 0; i < def->num_services; i++)
00706 if (streq(request->service, def->services[i]->name))
00707 break;
00708 if (i == def->num_services) return FALSE;
00709
00710
00711 svc = def->services[i];
00712 for (i = 0; i < svc->num_ports; i++)
00713 if (streq(request->port, svc->ports[i]->name))
00714 break;
00715 if (i == svc->num_ports) return FALSE;
00716
00717
00718 pt = svc->ports[i]->port_type;
00719 for (i = 0; i < pt->num_operations; i++)
00720 if (streq(request->operation, pt->operations[i]->name))
00721 break;
00722 if (i == pt->num_operations) return FALSE;
00723
00724
00725 return can_service_parts(request, pt->operations[i]);
00726 }
00727
00728
00735 static bs_status check_types(const bs_service_request *request)
00736 {
00737 bs_uint16 i;
00738 for (i = 0; i < request->input->num_parts; i++) {
00739 bs_part_instance *inst = request->input->parts[i];
00740 if (is_builtin_type(inst->type->name) && check_builtin_type(inst) != BS_OK)
00741 return BS_ERROR;
00742 }
00743 return BS_OK;
00744 }
00745
00746
00747 bs_bool request_corresponds_with_definition(const bs_service_request *request,
00748 const bs_definition *def)
00749 {
00750
00751
00752 if (!can_service(request, def)) return FALSE;
00753
00754
00755 if (check_types(request) != BS_OK) return FALSE;
00756
00757 return TRUE;
00758 }