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
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 #include <sys/types.h>
00115 #include <sys/socket.h>
00116 #include <unistd.h>
00117 #include <errno.h>
00118 #include <time.h>
00119 #include <limits.h>
00120
00121 #include "gwlib/gwlib.h"
00122 #include "gwlib/http.h"
00123 #include "smscconn.h"
00124 #include "smscconn_p.h"
00125 #include "bb_smscconn_cb.h"
00126 #include "msg.h"
00127 #include "sms.h"
00128 #include "dlr.h"
00129
00130
00131 #include <libxml/xmlmemory.h>
00132 #include <libxml/parser.h>
00133
00134
00135 #define SOAP_SLEEP_TIME 0.01
00136 #define SOAP_MAX_MESSAGE_PER_ROUND 1
00137 #define SOAP_DEFAULT_SENDER_STRING "Kannel"
00138 #define SOAP_DEFAULT_VALIDITY 60
00139
00140
00141 #define SOAP_MO_URI "/mo"
00142 #define SOAP_DLR_URI "/dlr"
00143
00144
00145 #define SOAP_DEFAULT_MESSAGE "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<Error>No method by that name</Error>"
00146 #define SOAP_ERROR_NO_DLR_MESSAGE "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<Error>Sorry - no DLR for that MT</Error>"
00147 #define SOAP_ERROR_DLR_MESSAGE "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<Error>Fatal error while trying to parse delivery report</Error>"
00148 #define SOAP_ERROR_MO_MESSAGE "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<Error>Fatal error while trying to parse incoming MO</Error>"
00149 #define SOAP_ERROR_NO_DATA_MESSAGE "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<Error>No data received</Error>"
00150 #define SOAP_ERROR_MALFORMED_DATA_MESSAGE "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<Error>Malformed data received</Error>"
00151
00152
00153 #define SOAP_ERROR_NO_DLR_CODE HTTP_BAD_METHOD
00154 #define SOAP_DEFAULT_CODE HTTP_NOT_FOUND
00155 #define SOAP_ERROR_DLR_CODE HTTP_INTERNAL_SERVER_ERROR
00156 #define SOAP_ERROR_MO_CODE HTTP_INTERNAL_SERVER_ERROR
00157 #define SOAP_ERROR_NO_DATA_CODE HTTP_NOT_IMPLEMENTED
00158 #define SOAP_ERROR_MALFORMED_DATA_CODE HTTP_BAD_GATEWAY
00159 #define SOAP_QUERY_OK HTTP_OK
00160
00161
00162 #undef HUMAN_TIME
00163
00164 #define MIN_SOAP_CLIENTS 5
00165 #define MAX_SOAP_CLIENTS 50
00166 #define CLIENT_BUSY_TIME 5
00167 #define CLIENT_TEARDOWN_TIME 600
00168 #define CLIENT_BUSY_LOAD 5
00169
00170 #define SPEC_DEFAULT "default"
00171
00172
00173 typedef struct privdata {
00174 List *outgoing_queue;
00175
00176 long listener_thread;
00177 long server_thread;
00178
00179 int shutdown;
00180 int soap_server;
00181
00182 long port;
00183 int ssl;
00184
00185 Octstr *uri;
00186
00187 Octstr *allow_ip, *deny_ip;
00188
00189 List* soap_client;
00190
00191 Octstr* name;
00192
00193
00194 Octstr* form_variable;
00195 int form_urlencoded;
00196 Octstr* alt_charset;
00197
00198 Octstr* mt_xml_file;
00199 Octstr* mt_spec_file;
00200 Octstr* mo_xml_file;
00201 Octstr* mo_spec_file;
00202 Octstr* dlr_xml_file;
00203 Octstr* dlr_spec_file;
00204 Octstr* mo_deps_file;
00205 } PrivData;
00206
00207
00208 typedef struct client_data {
00209 time_t last_access;
00210 unsigned long requests;
00211 HTTPCaller* caller;
00212 } ClientData;
00213
00214
00215 typedef struct argument_map {
00216 Octstr* name;
00217 Octstr* path;
00218 Octstr* attribute;
00219 Octstr* sscan_type;
00220 void* store;
00221 } ArgumentMap;
00222
00223
00224
00225 #define O_DESTROY(a) { if(a) octstr_destroy(a); a=NULL; }
00226
00227
00228
00229
00230
00231
00232 int smsc_soap_create(SMSCConn *conn, CfgGroup *cfg);
00233
00234 static int soap_add_msg_cb(SMSCConn *conn, Msg *sms);
00235
00236 static int soap_shutdown_cb(SMSCConn *conn, int finish_sending);
00237
00238 static void soap_start_cb(SMSCConn *conn);
00239
00240 static void soap_stop_cb(SMSCConn *conn);
00241
00242 static long soap_queued_cb(SMSCConn *conn);
00243
00244
00245
00246
00247
00248
00249 static void soap_listener(void *arg);
00250
00251 static void soap_server(void *arg);
00252
00253
00254
00255
00256
00257
00258 static void soap_send_loop(SMSCConn *conn);
00259
00260 static void soap_send(PrivData *privdata, Octstr *xmlbuffer, Msg *msgid);
00261
00262 static void soap_read_response(SMSCConn *conn);
00263
00264 static Octstr *soap_format_xml(Octstr *xml_file, Msg *msg, PrivData *privdata);
00265
00266
00267 static long long soap_parse_response(PrivData *privdata, Octstr *xmlResponse);
00268
00269 static long soap_parse_mo(SMSCConn *conn, Octstr *request, Octstr **response);
00270
00271 static long soap_parse_dlr(SMSCConn *conn, Octstr *request, Octstr **response);
00272
00273
00274
00275
00276
00277 int soap_xmlnode_get_long(xmlNodePtr cur, long *out);
00278
00279 int soap_xmlnode_get_int64(xmlNodePtr cur, long long *out);
00280
00281 int soap_xmlnode_get_octstr(xmlNodePtr cur, Octstr **out);
00282
00283 time_t soap_read_date(Octstr *dateString);
00284
00285 static Octstr *soap_write_date(time_t date);
00286
00287 int soap_server_start(SMSCConn *conn);
00288
00289 static void soap_server_stop(PrivData *privdata);
00290
00291 static ClientData *soap_create_client_data();
00292
00293 static void soap_destroy_client_data(void *data);
00294
00295 static void soap_client_init_query(PrivData *privdata, List *headers, Octstr *data, Msg *msg);
00296
00297 static ClientData *soap_client_have_response(List *client_list);
00298
00299 static Octstr *soap_convert_token(Msg *msg, Octstr *name, PrivData *privdata);
00300
00301 List *soap_create_map(Octstr* spec, long count, char* keywords[], char* types[], void* storage[]);
00302
00303 void soap_destroy_map(void *item);
00304
00305 int soap_map_xml_data(xmlNodePtr xml, List* maps);
00306
00307 Octstr* soap_fetch_xml_data(xmlNodePtr xml, Octstr* path);
00308
00309
00310
00311 long soap_release_dependences(Octstr* deps, List* lstmaps, Msg* msg, PrivData *privdata);
00312
00313 int soap_process_deps(int key_index, int key_func_ind, Msg* msg, PrivData *privdata);
00314
00315
00316 int soap_msgtype_deps(int key_func_index, Msg* msg);
00317 int soap_msgdata_deps(int key_func_index, Msg* msg, PrivData *privdata);
00318
00319
00320
00321 int soap_lookup_function(Octstr* funcname);
00322
00323
00324 Octstr* soap_select_function(int index, Msg* msg, PrivData* privdata);
00325
00326 Octstr* soap_bouyg_content_attribute(Msg* msg);
00327 Octstr* soap_mobitai_content_attribute(Msg* msg);
00328 Octstr* soap_o2o_msgdata_attribute(Msg* msg, PrivData *privdata);
00329 Octstr* soap_msgdata_attribute(Msg* msg, PrivData* privdata);
00330 Octstr* soap_o2o_validity30_attribute(Msg* msg);
00331 Octstr* soap_mobitai_validity_date_attribute(Msg* msg);
00332 Octstr* soap_bouyg_validity_attribute(Msg* msg);
00333 Octstr* soap_o2o_date_attribute(Msg* msg);
00334 Octstr* soap_mobitai_date_attribute(Msg* msg);
00335 Octstr* soap_rand_attribute(Msg* msg);
00336 Octstr* soap_o2o_dlrmask_smsc_yn_attribute(Msg* msg);
00337 Octstr* soap_o2o_dlrmask_success_01_attribute(Msg* msg);
00338
00339
00340 int soap_get_index(List* where, Octstr* key, int map_index);
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354 int smsc_soap_create(SMSCConn *conn, CfgGroup *cfg)
00355 {
00356 PrivData *privdata;
00357 Octstr* temp = NULL;
00358 List* filenames = NULL;
00359
00360
00361 privdata = gw_malloc(sizeof(PrivData));
00362 privdata->outgoing_queue = gwlist_create();
00363
00364
00365 privdata->shutdown = 0;
00366 privdata->soap_client = NULL;
00367 privdata->soap_server = 0;
00368
00369
00370 if (cfg_get_integer(&(privdata->port), cfg, octstr_imm("receive-port-ssl")) == -1)
00371 if (cfg_get_integer(&(privdata->port), cfg, octstr_imm("receive-port")) == -1)
00372 privdata->port = 0;
00373 else
00374 privdata->ssl = 0;
00375 else
00376
00377 privdata->ssl = 1;
00378
00379 privdata->uri = cfg_get(cfg, octstr_imm("send-url"));
00380
00381 privdata->allow_ip = cfg_get(cfg, octstr_imm("connect-allow-ip"));
00382 if (privdata->allow_ip)
00383 privdata->deny_ip = octstr_create("*.*.*.*");
00384 else
00385 privdata->deny_ip = NULL;
00386
00387
00388 privdata->form_variable = cfg_get(cfg, octstr_imm("form-variable"));
00389 cfg_get_bool(&(privdata->form_urlencoded), cfg, octstr_imm("form-urlencoded"));
00390
00391 privdata->alt_charset = cfg_get(cfg, octstr_imm("alt-charset"));
00392 if (!privdata->alt_charset)
00393 privdata->alt_charset = octstr_create("utf-8");
00394
00395
00396 if (privdata->port <= 0 || privdata->port > 65535) {
00397 error(0, "invalid port definition for SOAP server (%ld) - aborting",
00398 privdata->port);
00399 goto error;
00400 }
00401
00402 if (!privdata->uri) {
00403 error(0, "invalid or missing send-url definition for SOAP - aborting.");
00404 goto error;
00405 }
00406
00407 if (!privdata->form_variable) {
00408 error(0, "invalid or missing form variable name definition for SOAP - aborting.");
00409 goto error;
00410 }
00411
00412
00413 filenames = octstr_split(temp = cfg_get(cfg,octstr_imm("xml-files")),
00414 octstr_imm(";"));
00415 octstr_destroy(temp);
00416 if (gwlist_len(filenames) < 3) {
00417 error(0,"SOAP: Not enough template files for XML generation, you need 3 - aborting");
00418 goto error;
00419 }
00420 if ( !(privdata->mt_xml_file = octstr_read_file(
00421 octstr_get_cstr(temp = gwlist_extract_first(filenames))))) {
00422 error(0,"SOAP: Can't load XML template for MT - aborting");
00423 goto error;
00424
00425 }
00426 octstr_destroy(temp);
00427 if ( !(privdata->mo_xml_file = octstr_read_file(
00428 octstr_get_cstr(temp = gwlist_extract_first(filenames))))) {
00429 error(0,"SOAP: Can't load XML template for MO - aborting");
00430 goto error;
00431 }
00432 octstr_destroy(temp);
00433 if ( !(privdata->dlr_xml_file = octstr_read_file(
00434 octstr_get_cstr(temp = gwlist_extract_first(filenames))))) {
00435
00436 error(0,"SOAP: Can't load XML template for DLR - aborting");
00437 goto error;
00438 }
00439 octstr_destroy(temp);
00440 gwlist_destroy(filenames, octstr_destroy_item);
00441
00442 filenames = octstr_split(temp = cfg_get(cfg,octstr_imm("xmlspec-files")),
00443 octstr_imm(";"));
00444 octstr_destroy(temp);
00445 if (gwlist_len(filenames) < 4) {
00446 error(0,"Not enough spec files for XML parsing, you need 4 - aborting");
00447 goto error;
00448 }
00449 if ( !(privdata->mt_spec_file = octstr_read_file(
00450 octstr_get_cstr(temp = gwlist_extract_first(filenames))))) {
00451 error(0,"Can't load spec for MT parsing - aborting");
00452 goto error;
00453 }
00454 octstr_destroy(temp);
00455 if ( !(privdata->mo_spec_file = octstr_read_file(
00456 octstr_get_cstr(temp = gwlist_extract_first(filenames))))) {
00457 error(0,"SOAP: Can't load spec for MO parsing - aborting");
00458 goto error;
00459 }
00460 octstr_destroy(temp);
00461 if ( !(privdata->dlr_spec_file = octstr_read_file(
00462 octstr_get_cstr(temp = gwlist_extract_first(filenames))))) {
00463 error(0,"SOAP: Can't load spec for DLR parsing - aborting");
00464 goto error;
00465 }
00466 octstr_destroy(temp);
00467
00468 if ( !(privdata->mo_deps_file = octstr_read_file(
00469 octstr_get_cstr(temp = gwlist_extract_first(filenames))))) {
00470 error(0,"SOAP: Can't load 'deps' file for MO processing - aborting");
00471 goto error;
00472 }
00473 octstr_destroy(temp);
00474
00475 gwlist_destroy(filenames, octstr_destroy_item);
00476
00477 debug("bb.soap.create",0,"Connecting to %s",
00478 octstr_get_cstr(privdata->uri));
00479
00480
00481 conn->data = privdata;
00482
00483
00484 conn->name = octstr_format("SOAP: %s", octstr_get_cstr(privdata->uri) );
00485 privdata->name = octstr_duplicate(conn->id);
00486
00487
00488 conn->status = SMSCCONN_CONNECTING;
00489 conn->connect_time = time(NULL);
00490
00491
00492 conn->shutdown = soap_shutdown_cb;
00493 conn->queued = soap_queued_cb;
00494 conn->start_conn = soap_start_cb;
00495 conn->stop_conn = soap_stop_cb;
00496 conn->send_msg = soap_add_msg_cb;
00497
00498 privdata->listener_thread = 0;
00499 privdata->server_thread = 0;
00500
00501
00502 if (!conn->is_stopped)
00503
00504 conn->status = SMSCCONN_CONNECTING;
00505 else
00506 conn->status = SMSCCONN_DISCONNECTED;
00507
00508
00509 if ((privdata->listener_thread = gwthread_create(soap_listener, conn)) == -1) {
00510 error(0, "SOAP: soap_create, failed to spawn thread - aborting");
00511 goto error;
00512 }
00513
00514 return 0;
00515
00516 error:
00517
00518 error(0, "SOAP: Failed to create SOAP smsc connection");
00519
00520
00521 if (privdata != NULL) {
00522 gwlist_destroy(privdata->outgoing_queue, NULL);
00523
00524
00525 O_DESTROY(privdata->uri);
00526 O_DESTROY(privdata->allow_ip);
00527 O_DESTROY(privdata->deny_ip);
00528 O_DESTROY(privdata->form_variable);
00529 O_DESTROY(privdata->alt_charset);
00530 O_DESTROY(privdata->name);
00531 O_DESTROY(privdata->mo_xml_file);
00532 O_DESTROY(privdata->dlr_xml_file);
00533 O_DESTROY(privdata->mt_xml_file);
00534 O_DESTROY(privdata->mo_spec_file);
00535 O_DESTROY(privdata->dlr_spec_file);
00536 O_DESTROY(privdata->mt_spec_file);
00537 O_DESTROY(privdata->mo_deps_file);
00538 }
00539 gw_free(privdata);
00540 octstr_destroy(temp);
00541 gwlist_destroy(filenames, octstr_destroy_item);
00542
00543
00544 conn->why_killed = SMSCCONN_KILLED_CANNOT_CONNECT;
00545 conn->status = SMSCCONN_DEAD;
00546
00547 info(0, "exiting");
00548 return -1;
00549 }
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563 static int soap_add_msg_cb(SMSCConn *conn, Msg *sms)
00564 {
00565
00566 PrivData *privdata = conn->data;
00567 Msg *copy;
00568
00569
00570 if (conn->status == SMSCCONN_DEAD)
00571 return -1;
00572
00573 copy = msg_duplicate(sms);
00574 gwlist_append(privdata->outgoing_queue, copy);
00575
00576 debug("bb.soap.add_msg",0,"SOAP[%s]: got a new MT from %s, list has now %ld MTs",
00577 octstr_get_cstr(privdata->name), octstr_get_cstr(sms->sms.sender),
00578 gwlist_len(privdata->outgoing_queue));
00579
00580 gwthread_wakeup(privdata->listener_thread);
00581
00582 return 0;
00583 }
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594 static int soap_shutdown_cb(SMSCConn *conn, int finish_sending)
00595 {
00596 PrivData *privdata = conn->data;
00597 long thread;
00598
00599
00600 if (conn->status == SMSCCONN_DEAD)
00601 return -1;
00602
00603 debug("bb.soap.cb", 0, "SOAP[%s]: Shutting down SMSCConn, %s",
00604 octstr_get_cstr(privdata->name), finish_sending ? "slow" : "instant");
00605
00606
00607
00608 conn->why_killed = SMSCCONN_KILLED_SHUTDOWN;
00609
00610
00611 privdata->shutdown = 1;
00612
00613 if (finish_sending == 0) {
00614 Msg *msg;
00615 while ((msg = gwlist_extract_first(privdata->outgoing_queue)) != NULL)
00616 bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_SHUTDOWN, NULL);
00617 }
00618
00619 thread = privdata->listener_thread;
00620
00621 gwthread_wakeup(thread);
00622 gwthread_join(thread);
00623
00624 return 0;
00625 }
00626
00627
00628
00629
00630
00631
00632
00633
00634 static void soap_start_cb(SMSCConn *conn)
00635 {
00636 PrivData *privdata = conn->data;
00637
00638 debug("smsc.soap.start", 0, "SOAP[%s]: start called",
00639 octstr_get_cstr(privdata->name));
00640
00641
00642 conn->status = SMSCCONN_CONNECTING;
00643
00644
00645 if ((!privdata->listener_thread) &&
00646 ((privdata->listener_thread = gwthread_create(soap_listener, conn)) == -1)) {
00647 error(0, "SOAP: soap_start, failed to spawn thread - aborting");
00648 conn->why_killed = SMSCCONN_KILLED_CANNOT_CONNECT;
00649 conn->status = SMSCCONN_DEAD;
00650 privdata->shutdown = 1;
00651 return;
00652 }
00653
00654 debug("smsc.soap.start",0,"SOAP[%s]: starting OK",
00655 octstr_get_cstr(privdata->name));
00656 }
00657
00658
00659
00660
00661
00662
00663
00664
00665 static void soap_stop_cb(SMSCConn *conn)
00666 {
00667 PrivData *privdata = conn->data;
00668
00669
00670 if (conn->status == SMSCCONN_DEAD)
00671 return;
00672
00673 debug("smsc.soap.stop", 0, "SOAP[%s]: stop called",
00674 octstr_get_cstr(privdata->name));
00675
00676
00677 conn->status = SMSCCONN_DISCONNECTED;
00678 }
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688 static long soap_queued_cb(SMSCConn *conn)
00689 {
00690 PrivData *privdata = conn->data;
00691 long ret;
00692
00693
00694 if (conn->status == SMSCCONN_DEAD)
00695 return -1;
00696
00697 ret = gwlist_len(privdata->outgoing_queue);
00698
00699
00700
00701 conn->load = ret;
00702
00703 return ret;
00704 }
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718 static void soap_listener(void *arg)
00719 {
00720 SMSCConn *conn = arg;
00721 PrivData *privdata = conn->data;
00722 Msg *msg = NULL;
00723 debug("bb.soap.listener",0,"SOAP[%s]: listener entering",
00724 octstr_get_cstr(privdata->name));
00725
00726 while (!privdata->shutdown) {
00727
00728
00729 switch (conn->status) {
00730 case SMSCCONN_RECONNECTING:
00731 case SMSCCONN_CONNECTING:
00732 if (privdata->soap_server) {
00733 soap_server_stop(privdata);
00734 }
00735
00736 if (soap_server_start(conn)) {
00737 privdata->shutdown = 1;
00738 error(0, "SOAP[%s]: failed to start HTTP server!",
00739 octstr_get_cstr(privdata->name));
00740 break;
00741 }
00742
00743 mutex_lock(conn->flow_mutex);
00744 conn->status = SMSCCONN_ACTIVE;
00745 mutex_unlock(conn->flow_mutex);
00746
00747 bb_smscconn_connected(conn);
00748 break;
00749
00750 case SMSCCONN_DISCONNECTED:
00751 if (privdata->soap_server)
00752 soap_server_stop(privdata);
00753 break;
00754
00755 case SMSCCONN_ACTIVE:
00756 if (!privdata->soap_server) {
00757 mutex_lock(conn->flow_mutex);
00758 conn->status = SMSCCONN_RECONNECTING;
00759 mutex_unlock(conn->flow_mutex);
00760 break;
00761 }
00762
00763
00764 if (gwlist_len(privdata->outgoing_queue) > 0) {
00765 soap_send_loop(conn);
00766 }
00767 break;
00768
00769 case SMSCCONN_DEAD:
00770
00771
00772
00773 default:
00774 break;
00775 }
00776
00777 soap_read_response(conn);
00778
00779
00780 gwthread_sleep(SOAP_SLEEP_TIME);
00781 }
00782
00783 debug("bb.soap.connection",0,"SOAP[%s]: connection shutting down",
00784 octstr_get_cstr(privdata->name));
00785
00786 soap_server_stop(privdata);
00787
00788
00789 debug("bb.soap.connection",0,"SOAP[%s]: sending messages back to bearerbox",
00790 octstr_get_cstr(privdata->name));
00791
00792 while ((msg = gwlist_extract_first(privdata->outgoing_queue)) != NULL)
00793 bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_SHUTDOWN, NULL);
00794
00795
00796 mutex_lock(conn->flow_mutex);
00797
00798 debug("bb.soap.connection",0,"SOAP[%s]: playing dead",
00799 octstr_get_cstr(privdata->name));
00800 conn->status = SMSCCONN_DEAD;
00801
00802
00803 debug("bb.soap.connection",0,"SOAP[%s]: don't need the queue anymore",
00804 octstr_get_cstr(privdata->name));
00805
00806 gwlist_destroy(privdata->outgoing_queue, NULL);
00807
00808
00809
00810 debug("bb.soap.connection",0,"SOAP[%s]: tell caller to stop",
00811 octstr_get_cstr(privdata->name));
00812 if (privdata->soap_client)
00813 gwlist_destroy(privdata->soap_client, soap_destroy_client_data);
00814
00815
00816 debug("bb.soap.connection",0,"SOAP[%s]: done with privdata",
00817 octstr_get_cstr(privdata->name));
00818 O_DESTROY(privdata->uri);
00819 O_DESTROY(privdata->allow_ip);
00820 O_DESTROY(privdata->deny_ip);
00821
00822 O_DESTROY(privdata->form_variable);
00823
00824 O_DESTROY(privdata->alt_charset);
00825 O_DESTROY(privdata->name);
00826 O_DESTROY(privdata->mo_xml_file);
00827
00828 O_DESTROY(privdata->dlr_xml_file);
00829 O_DESTROY(privdata->mt_xml_file);
00830 O_DESTROY(privdata->mo_spec_file);
00831 O_DESTROY(privdata->dlr_spec_file);
00832 O_DESTROY(privdata->mt_spec_file);
00833 O_DESTROY(privdata->mo_deps_file);
00834
00835 gw_free(privdata);
00836 conn->data = NULL;
00837
00838 mutex_unlock(conn->flow_mutex);
00839
00840 debug("bb.soap.connection", 0, "SOAP: module has completed shutdown.");
00841 bb_smscconn_killed();
00842 }
00843
00844
00845
00846
00847
00848
00849
00850 static void soap_server(void* arg)
00851 {
00852 SMSCConn* conn = (SMSCConn*)arg;
00853 PrivData* privdata = conn->data;
00854
00855
00856 HTTPClient* remote_client = NULL;
00857 List *request_headers = NULL, *response_headers = NULL;
00858 List *cgivars = NULL;
00859 Octstr *client_ip = NULL, *request_uri = NULL, *request_body = NULL;
00860 Octstr *response_body = NULL;
00861 Octstr *timebuf = NULL;
00862 int http_response_status;
00863
00864 debug("bb.soap.server",0,"SOAP[%s]: Server starting",
00865 octstr_get_cstr(privdata->name));
00866
00867
00868 response_headers = http_create_empty_headers();
00869 http_header_add(response_headers, "Content-type","text/xml");
00870
00871
00872 http_header_add(response_headers, "Server","Kannel");
00873
00874 while (privdata->soap_server) {
00875 if ((remote_client = http_accept_request(privdata->port,
00876 &client_ip, &request_uri, &request_headers,
00877 &request_body, &cgivars))) {
00878
00879 debug("bb.soap.server",0,"SOAP[%s]: server got a request for "
00880 "%s from %s, with body <%s>", octstr_get_cstr(privdata->name),
00881 octstr_get_cstr(request_uri),octstr_get_cstr(client_ip),
00882 request_body ? octstr_get_cstr(request_body) : "<null>");
00883
00884
00885 if (!octstr_compare(request_uri,octstr_imm(SOAP_MO_URI))) {
00886
00887 if ((http_response_status =
00888 soap_parse_mo(conn,request_body, &response_body)) == -1) {
00889
00890 error(0,"SOAP[%s]: fatal error parsing MO",
00891 octstr_get_cstr(privdata->name));
00892 response_body = octstr_create(SOAP_ERROR_MO_MESSAGE);
00893 http_response_status = SOAP_ERROR_MO_CODE;
00894 }
00895 } else if (!octstr_compare(request_uri,octstr_imm(SOAP_DLR_URI))) {
00896
00897 if ((http_response_status =
00898 soap_parse_dlr(conn,request_body, &response_body)) == -1) {
00899
00900 error(0,"SOAP[%s]: fatal error parsing DLR",
00901 octstr_get_cstr(privdata->name));
00902 response_body = octstr_create(SOAP_ERROR_DLR_MESSAGE);
00903 http_response_status = SOAP_ERROR_DLR_CODE;
00904 }
00905 } else {
00906
00907 response_body = octstr_create(SOAP_DEFAULT_MESSAGE);
00908 http_response_status = SOAP_DEFAULT_CODE;
00909 }
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924 timebuf = date_format_http(time(NULL));
00925
00926 O_DESTROY(timebuf);
00927
00928
00929
00930 http_send_reply(remote_client,http_response_status,response_headers, response_body);
00931
00932
00933
00934 O_DESTROY(response_body);
00935
00936
00937 O_DESTROY(request_uri);
00938 O_DESTROY(request_body);
00939 O_DESTROY(client_ip);
00940
00941 http_destroy_headers(request_headers);
00942 gwlist_destroy(cgivars, NULL);
00943 }
00944
00945 gwthread_sleep(SOAP_SLEEP_TIME);
00946 }
00947
00948 debug("bb.soap.server",0,"SOAP[%s]: server going down",
00949 octstr_get_cstr(privdata->name));
00950
00951 }
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963 static void soap_send_loop(SMSCConn* conn)
00964 {
00965 PrivData* privdata = conn->data;
00966 Msg *msg;
00967 Octstr* xmldata = NULL;
00968 int counter = 0;
00969
00970 debug("bb.soap.client",0,"SOAP[%s]: client - entering",
00971 octstr_get_cstr(privdata->name));
00972
00973 while ((counter < SOAP_MAX_MESSAGE_PER_ROUND) &&
00974 (msg = gwlist_extract_first(privdata->outgoing_queue))) {
00975
00976 ++counter;
00977
00978 if (uuid_is_null(msg->sms.id))
00979 uuid_generate(msg->sms.id);
00980
00981
00982 if (!(xmldata = soap_format_xml(privdata->mt_xml_file, msg, privdata))) {
00983 debug("bb.soap.client",0,"SOAP[%s]: client - failed to format message for sending",
00984 octstr_get_cstr(privdata->name));
00985 bb_smscconn_send_failed(conn, msg,
00986 SMSCCONN_FAILED_MALFORMED, octstr_create("MALFORMED"));
00987 continue;
00988 }
00989
00990 debug("bb.soap.client",0,"SOAP[%s]: client - Sending message <%s>",
00991 octstr_get_cstr(privdata->name), octstr_get_cstr(msg->sms.msgdata));
00992 if (xmldata)
00993 debug("bb.soap.client",0,"SOAP[%s]: data dump: %s",
00994 octstr_get_cstr(privdata->name), octstr_get_cstr(xmldata));
00995
00996
00997 soap_send(privdata, xmldata, msg);
00998
00999
01000
01001
01002
01003 O_DESTROY(xmldata);
01004 }
01005 }
01006
01007
01008
01009
01010
01011
01012
01013
01014 static Octstr *soap_format_xml(Octstr *xml_file, Msg *msg, PrivData *privdata)
01015 {
01016 Octstr *xml;
01017 long t;
01018 long start = -1;
01019 int curly_enclose = 0;
01020
01021 xml = octstr_create("");
01022
01023 for (t = 0; t < octstr_len(xml_file); ++t) {
01024 unsigned char c;
01025
01026 if ((c = octstr_get_char(xml_file,t)) == '%') {
01027
01028 start = t+1;
01029 continue;
01030 }
01031
01032 if (c == '{' && start == t) {
01033 ++start;
01034 curly_enclose=1;
01035 }
01036
01037 if (start < 0)
01038 octstr_append_char(xml,c);
01039 else if (
01040 (curly_enclose && (c == '}'))
01041 ||
01042 (!curly_enclose && !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
01043 (c >= '0' && c <= '9') || c == '_'))) {
01044
01045 Octstr *data, *token;
01046
01047 token = octstr_copy(xml_file,start,(t-start));
01048 if ((data = soap_convert_token(msg, token, privdata))) {
01049 octstr_append(xml, data);
01050 octstr_destroy(data);
01051 } else {
01052 error(0,"SOAP: format_xml - failed to format token %s using message",
01053 octstr_get_cstr(token));
01054 octstr_destroy(token);
01055 octstr_destroy(xml);
01056 return NULL;
01057
01058 }
01059 octstr_destroy(token);
01060 start = -1;
01061 if (!curly_enclose)
01062
01063
01064 --t;
01065 else
01066 curly_enclose = 0;
01067 }
01068 }
01069
01070 return xml;
01071 }
01072
01073
01074
01075
01076
01077
01078
01079
01080 static void soap_send(PrivData* privdata, Octstr* xmlbuffer, Msg* msg)
01081 {
01082 List *requestHeaders;
01083 Octstr* postdata;
01084
01085
01086 requestHeaders = http_create_empty_headers();
01087 http_header_add(requestHeaders, "User-Agent", "Kannel " GW_VERSION);
01088
01089 if (privdata->form_urlencoded) {
01090 http_header_add(requestHeaders, "Content-Type", "application/x-www-form-urlencoded");
01091 postdata = octstr_format("%S=%E", privdata->form_variable, xmlbuffer);
01092 } else {
01093 http_header_add(requestHeaders, "Content-Type", "multipart/form-data, boundary=AaB03x");
01094 postdata = octstr_format("--AaB03x\r\n"
01095 "content-disposition: form-data; name=\"%S\"\r\n\r\n%S",
01096 privdata->form_variable, xmlbuffer);
01097 }
01098
01099
01100 soap_client_init_query(privdata, requestHeaders, postdata, msg);
01101
01102 O_DESTROY(postdata);
01103
01104
01105 http_destroy_headers(requestHeaders);
01106
01107 return;
01108
01109 }
01110
01111
01112
01113
01114
01115
01116
01117
01118 static void soap_read_response(SMSCConn *conn)
01119 {
01120 PrivData *privdata = conn->data;
01121 Msg* msg;
01122 Octstr *responseBody, *responseURL;
01123 List* responseHeaders;
01124 int responseStatus;
01125 long long msgID;
01126 ClientData* cd;
01127
01128
01129
01130 if (!gwlist_len(privdata->soap_client))
01131 return;
01132
01133
01134
01135 if (!(cd = soap_client_have_response(privdata->soap_client)))
01136 return;
01137
01138 cd->requests--;
01139 msg = http_receive_result(cd->caller, &responseStatus, &responseURL, &responseHeaders, &responseBody);
01140
01141 if (!msg)
01142 {
01143 debug("bb.soap.read_response",0,"SOAP[%s]: sorry, no response", octstr_get_cstr(privdata->name));
01144 return;
01145 }
01146
01147 if (responseStatus == -1) {
01148 debug("bb.soap.read_response",0,"SOAP[%s]: HTTP connection failed - blame the server (requeing msg)",
01149 octstr_get_cstr(privdata->name));
01150 bb_smscconn_send_failed(conn, msg,
01151 SMSCCONN_FAILED_MALFORMED, octstr_create("MALFORMED"));
01152
01153
01154 return;
01155 }
01156
01157 debug("bb.soap.read_response",0,"SOAP[%s]: got a response %d= %s",
01158 octstr_get_cstr(privdata->name), responseStatus, responseBody?octstr_get_cstr(responseBody):octstr_get_cstr(octstr_imm("NULL")));
01159
01160
01161
01162 if ( (msgID = soap_parse_response(privdata, responseBody)) >= 0)
01163 {
01164 char tmpid[30];
01165
01166
01167
01168
01169
01170
01171
01172
01173 sprintf(tmpid,"%lld",msgID);
01174 debug("bb.soap.read_response",0,"SOAP[%s]: ACK - id: %lld", octstr_get_cstr(privdata->name), msgID);
01175
01176 dlr_add(conn->id, octstr_imm(tmpid), msg);
01177
01178
01179 bb_smscconn_sent(conn, msg, NULL);
01180 }
01181
01182 else {
01183 debug("bb.soap.read_response",0,"SOAP[%s]: NACK", octstr_get_cstr(privdata->name));
01184
01185
01186 bb_smscconn_send_failed(conn, msg,
01187 SMSCCONN_FAILED_MALFORMED, octstr_create("MALFORMED"));
01188 }
01189
01190 http_destroy_headers(responseHeaders);
01191 O_DESTROY(responseBody);
01192 O_DESTROY(responseURL);
01193 }
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205 static long long soap_parse_response(PrivData* privdata, Octstr* xmlResponse)
01206 {
01207 long long msgID = -1;
01208 long responseStatus = -1;
01209 xmlDocPtr responseDoc;
01210 xmlNodePtr root;
01211 List* maps;
01212 char* keywords[] = { "id", "result" };
01213 char* sscans[] = { "%lld", "%ld" };
01214 void* pointers[] = { &msgID, &responseStatus };
01215
01216 if (!xmlResponse)
01217 return -1;
01218
01219
01220
01221 if ( !(responseDoc = xmlParseDoc((xmlChar *)octstr_get_cstr(xmlResponse))) ) {
01222 error(0,"SOAP[%s]: couldn't parse XML response [ %s ] in MT parsing",
01223 octstr_get_cstr(privdata->name), octstr_get_cstr(xmlResponse));
01224 return -1;
01225 }
01226
01227
01228 if ( ! (root = xmlDocGetRootElement(responseDoc)) ) {
01229 error(0,"SOAP[%s]: couldn't get XML root element in MT parsing",
01230 octstr_get_cstr(privdata->name));
01231 xmlFreeDoc(responseDoc);
01232 return -1;
01233 }
01234
01235
01236 maps = soap_create_map(privdata->mt_spec_file, 2, keywords, sscans, pointers);
01237
01238
01239 if (soap_map_xml_data(root, maps) < 2) {
01240 error(0,"SOAP[%s]: failed to map all the arguments from the XML data",
01241 octstr_get_cstr(privdata->name));
01242 }
01243
01244 gwlist_destroy(maps, soap_destroy_map);
01245
01246
01247 xmlFreeDoc(responseDoc);
01248
01249 if (msgID == -1) {
01250 if (responseStatus == 0) {
01251 warning(0, "SOAP[%s]: parse_response - the protocol does not support message ID",
01252 octstr_get_cstr(privdata->name));
01253 return 0;
01254 }
01255 else {
01256 error(0,"SOAP[%s]: parse_response - response code isn't 0 ! (%ld)",
01257 octstr_get_cstr(privdata->name), responseStatus);
01258 return -1;
01259 }
01260 }
01261 else
01262 return msgID;
01263
01264 }
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275 static long soap_parse_mo(SMSCConn *conn, Octstr *request, Octstr **response)
01276 {
01277 PrivData *privdata = conn->data;
01278 xmlDocPtr requestDoc;
01279 xmlNodePtr root;
01280
01281 Msg* msg;
01282 int pos = 0;
01283
01284 long res = -1;
01285
01286 List* maps;
01287 char receiver[30], sender[30], msgtype[30], msgdata[255], date[30];
01288 long long msgid = -1;
01289 char* keywords[] = { "receiver", "sender", "msgtype", "msgdata", "date", "id" };
01290 char* sscans[] = { "%s", "%s", "%s", "%s", "%s", "%lld" };
01291 void* pointers[] = { &receiver, &sender, &msgtype, &msgdata, &date, &msgid };
01292
01293 receiver[0] = sender[0] = msgtype[0] = msgdata[0] = date[0] = '\0';
01294
01295 if (!response)
01296 return -1;
01297
01298 if (!request) {
01299 *response = octstr_create(SOAP_ERROR_NO_DATA_MESSAGE);
01300 return SOAP_ERROR_NO_DATA_CODE;
01301 }
01302
01303
01304 if ( (pos = octstr_search_char(request,'=',0)) < 0) {
01305
01306 *response = octstr_create(SOAP_ERROR_MALFORMED_DATA_MESSAGE);
01307 return SOAP_ERROR_MALFORMED_DATA_CODE;
01308 }
01309
01310
01311 octstr_delete(request,0,pos+1);
01312
01313
01314 if (octstr_url_decode(request) < 0) {
01315
01316
01317 *response = octstr_create(SOAP_ERROR_MALFORMED_DATA_MESSAGE);
01318 return SOAP_ERROR_MALFORMED_DATA_CODE;
01319 }
01320
01321 debug("bb.soap.parse_mo",0,"SOAP[%s]: parse_mo - MO request dump <%s>", octstr_get_cstr(privdata->name),octstr_get_cstr(request));
01322
01323
01324 if ( !(requestDoc = xmlParseDoc((xmlChar *)octstr_get_cstr(request))) ) {
01325 error(0,"SOAP[%s]: parse_mo couldn't parse XML response", octstr_get_cstr(privdata->name));
01326 return -1;
01327 }
01328
01329
01330 if ( ! (root = xmlDocGetRootElement(requestDoc)) ) {
01331 error(0,"SOAP[%s]: parse_mo couldn't get XML root element for request", octstr_get_cstr(privdata->name));
01332 xmlFreeDoc(requestDoc);
01333 return -1;
01334 }
01335
01336
01337 maps = soap_create_map(privdata->mo_spec_file, 6, keywords, sscans, pointers);
01338
01339
01340
01341 if (soap_map_xml_data(root, maps) < gwlist_len(maps)) {
01342 error(0,"SOAP[%s]: parse_mo failed to map all the arguments from the XML data",
01343 octstr_get_cstr(privdata->name));
01344 }
01345
01346
01347 xmlFreeDoc(requestDoc);
01348
01349 if (strlen(receiver) == 0) {
01350 error(0,"SOAP: parse_mo - failed to get receiver");
01351 *response = octstr_create(SOAP_ERROR_MALFORMED_DATA_MESSAGE);
01352 return SOAP_ERROR_MALFORMED_DATA_CODE;
01353 }
01354
01355 if (strlen(sender) == 0) {
01356 error(0,"SOAP: parse_mo - failed to get sender");
01357 *response = octstr_create(SOAP_ERROR_MALFORMED_DATA_MESSAGE);
01358 return SOAP_ERROR_MALFORMED_DATA_CODE;
01359 }
01360
01361 if (strlen(msgdata) == 0) {
01362 error(0,"SOAP: parse_mo - failed to get message content");
01363 *response = octstr_create(SOAP_ERROR_MALFORMED_DATA_MESSAGE);
01364
01365 return SOAP_ERROR_MALFORMED_DATA_CODE;
01366 }
01367
01368
01369
01370 msg = msg_create(sms);
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382 msg->sms.sender = octstr_create(sender);
01383 msg->sms.receiver = octstr_create(receiver);
01384
01385
01386
01387
01388 msg->sms.msgdata = octstr_create(msgdata);
01389
01390
01391 if (privdata->mo_deps_file) {
01392 if ((res = soap_release_dependences(privdata->mo_deps_file, maps, msg, privdata))!=0)
01393 error(0,"SOAP: parse_mo - failed to release all dependences");
01394 }
01395 gwlist_destroy(maps, soap_destroy_map);
01396
01397
01398 if (strlen(date)) {
01399 struct universaltime tm;
01400 Octstr* temp = octstr_create(date);
01401 if (date_parse_iso(&tm, temp))
01402
01403 msg->sms.time = time(NULL);
01404 else
01405 msg->sms.time = date_convert_universal(&tm);
01406 octstr_destroy(temp);
01407 } else
01408 msg->sms.time = time(NULL);
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477 if (!(msg->sms.sender)
01478 ||
01479 !(msg->sms.msgdata)) {
01480
01481 *response = octstr_create(SOAP_ERROR_MALFORMED_DATA_MESSAGE);
01482 return SOAP_ERROR_MALFORMED_DATA_CODE;
01483 }
01484
01485
01486 if (msg->sms.time <= 0)
01487 msg->sms.time = time(NULL);
01488
01489 if (!msg->sms.receiver)
01490 msg->sms.receiver = octstr_create(SOAP_DEFAULT_SENDER_STRING);
01491
01492 if (!msg->sms.smsc_id)
01493 msg->sms.smsc_id = octstr_duplicate(conn->id);
01494
01495 *response = soap_format_xml(privdata->mo_xml_file,msg,privdata);
01496 if (*response)
01497 debug("bb.soap.reponse_dlr",0,"SOAP[%s]: data dump: %s", octstr_get_cstr(privdata->name), octstr_get_cstr(*response));
01498
01499 bb_smscconn_receive(conn,msg);
01500
01501 return SOAP_QUERY_OK;
01502 }
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512 static long soap_parse_dlr(SMSCConn *conn, Octstr *request, Octstr **response)
01513 {
01514 PrivData *privdata = conn->data;
01515 xmlDocPtr requestDoc;
01516 xmlNodePtr root;
01517 Msg* dlrmsg = NULL;
01518 long dlrtype;
01519 int pos;
01520
01521 List* maps;
01522 char receiver[30], soapdate[30], msgid[30];
01523 long result = -1;
01524 char* keywords[] = { "receiver", "soapdate", "id", "result" };
01525
01526 char* sscans[] = { "%s", "%s", "%s", "%ld" };
01527 void* pointers[] = { &receiver, &soapdate, &msgid, &result };
01528
01529 receiver[0] = soapdate[0] = msgid[0] = '\0';
01530
01531 if (!response)
01532 return -1;
01533
01534 if (!request) {
01535 *response = octstr_create(SOAP_ERROR_NO_DATA_MESSAGE);
01536 return SOAP_ERROR_NO_DATA_CODE;
01537 }
01538
01539
01540 if ( (pos = octstr_search_char(request,'=',0)) < 0) {
01541
01542 *response = octstr_create(SOAP_ERROR_MALFORMED_DATA_MESSAGE);
01543 return SOAP_ERROR_MALFORMED_DATA_CODE;
01544 }
01545
01546
01547 octstr_delete(request,0,pos+1);
01548
01549
01550 if (octstr_url_decode(request) < 0) {
01551
01552 *response = octstr_create(SOAP_ERROR_MALFORMED_DATA_MESSAGE);
01553 return SOAP_ERROR_MALFORMED_DATA_CODE;
01554 }
01555
01556 debug("bb.soap.parse_dlr",0,"SOAP[%s]: parse_dlr - DLR request dump <%s>", octstr_get_cstr(privdata->name),octstr_get_cstr(request));
01557
01558
01559
01560 if ( !(requestDoc = xmlParseDoc((xmlChar *)octstr_get_cstr(request))) ) {
01561 error(0,"SOAP[%s]: parse_dlr couldn't parse XML response", octstr_get_cstr(privdata->name));
01562 return -1;
01563 }
01564
01565
01566 if ( ! (root = xmlDocGetRootElement(requestDoc)) ) {
01567
01568 error(0,"SOAP[%s]: parse_dlr couldn't get XML root element for request", octstr_get_cstr(privdata->name));
01569 xmlFreeDoc(requestDoc);
01570 return -1;
01571 }
01572
01573
01574
01575 maps = soap_create_map(privdata->dlr_spec_file, 4, keywords, sscans, pointers);
01576
01577
01578 if (soap_map_xml_data(root, maps) < 4) {
01579 error(0,"SOAP[%s]: parse_dlr failed to map all the arguments from the XML data",
01580
01581 octstr_get_cstr(privdata->name));
01582 }
01583
01584 gwlist_destroy(maps, soap_destroy_map);
01585
01586
01587 xmlFreeDoc(requestDoc);
01588
01589 if (strlen(msgid) == 0) {
01590 error(0,"SOAP: parse_dlr - failed to get message ID");
01591 *response = octstr_create(SOAP_ERROR_MALFORMED_DATA_MESSAGE);
01592 return SOAP_ERROR_MALFORMED_DATA_CODE;
01593 }
01594
01595 if (result == -1) {
01596
01597 error(0,"SOAP: parse_dlr - failed to get delivery code");
01598 *response = octstr_create(SOAP_ERROR_MALFORMED_DATA_MESSAGE);
01599 return SOAP_ERROR_MALFORMED_DATA_CODE;
01600 }
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610 debug("bb.soap.parse_dlr",0,"SOAP[%s]: parse_dlr DELIVERY_CODE : %ld", octstr_get_cstr(privdata->name),result);
01611 if (result == 0)
01612 dlrtype = DLR_SUCCESS;
01613 else
01614 dlrtype = DLR_FAIL;
01615
01616
01617
01618 dlrmsg = dlr_find(conn->id, octstr_imm(msgid), octstr_imm("receiver"),
01619 dlrtype);
01620
01621 if (!dlrmsg) {
01622 error(0,"SOAP[%s]: parse_dlr invoked (%ld), but no DLR found for MsgID %s", octstr_get_cstr(privdata->name),dlrtype,msgid);
01623 *response = octstr_create(SOAP_ERROR_NO_DLR_MESSAGE);
01624 return SOAP_ERROR_NO_DLR_CODE;
01625 }
01626
01627 debug("bb.soap.parse_dlr",0,"SOAP[%s]: parse_dlr found dlr", octstr_get_cstr(privdata->name));
01628 octstr_destroy(dlrmsg->sms.msgdata);
01629 switch (dlrtype) {
01630 case DLR_SUCCESS:
01631 dlrmsg->sms.msgdata = octstr_create("Delivered");
01632 break;
01633 case DLR_BUFFERED:
01634 dlrmsg->sms.msgdata = octstr_create("Buffered");
01635 break;
01636 case DLR_FAIL:
01637 dlrmsg->sms.msgdata = octstr_create("Failed");
01638 break;
01639 default:
01640 break;
01641
01642 }
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653 debug("bb.soap.parse_dlr",0,"SOAP[%s]: parse_dlr sent dlr <%s>", octstr_get_cstr(privdata->name),octstr_get_cstr(dlrmsg->sms.msgdata));
01654
01655
01656 *response = soap_format_xml(privdata->dlr_xml_file, dlrmsg, privdata);
01657 if (*response)
01658 debug("bb.soap.reponse_dlr",0,"SOAP[%s]: data dump: %s", octstr_get_cstr(privdata->name), octstr_get_cstr(*response));
01659
01660
01661 bb_smscconn_receive(conn, dlrmsg);
01662
01663 return SOAP_QUERY_OK;
01664
01665 }
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679 int soap_xmlnode_get_long(xmlNodePtr cur, long* out)
01680 {
01681 xmlChar* nodeContent;
01682 char* endPointer;
01683
01684 if (!out)
01685 return -1;
01686
01687
01688 if (!(nodeContent = xmlNodeGetContent(cur))) {
01689 error(0,"SOAP: get_long - xml Node has content !");
01690 return -1;
01691 }
01692
01693
01694 *out = strtol((char *)nodeContent,&endPointer,10);
01695 xmlFree(nodeContent);
01696
01697 if (endPointer == (char*)nodeContent) {
01698 error(0,"SOAP: get_long - node has non-numeric content <%s>", nodeContent);
01699 return -1;
01700 }
01701
01702 return 0;
01703 }
01704
01705
01706
01707
01708
01709
01710
01711
01712 int soap_xmlnode_get_int64(xmlNodePtr cur, long long* out)
01713 {
01714 xmlChar* nodeContent;
01715 char* endPointer;
01716
01717 if (!out)
01718 return -1;
01719
01720
01721 if (!(nodeContent = xmlNodeGetContent(cur))) {
01722 error(0,"SOAP: get_long - xml Node has content !");
01723 return -1;
01724 }
01725
01726
01727
01728 *out = strtoll((char *)nodeContent,&endPointer,10);
01729 xmlFree(nodeContent);
01730
01731 if (endPointer == (char*)nodeContent) {
01732 error(0,"SOAP: get_long - node has non-numeric content <%s>", nodeContent);
01733 return -1;
01734 }
01735
01736 return 0;
01737 }
01738
01739
01740
01741
01742
01743
01744
01745
01746 int soap_xmlnode_get_octstr(xmlNodePtr cur, Octstr **out)
01747 {
01748 xmlChar* nodeContent;
01749
01750 if (!out)
01751 return -1;
01752
01753
01754 if (!(nodeContent = xmlNodeGetContent(cur))) {
01755 error(0,"SOAP: get_octstr - xml Node has content !");
01756 return -1;
01757 }
01758
01759
01760 *out = octstr_create((char *)nodeContent);
01761 xmlFree(nodeContent);
01762
01763 if (*out)
01764 return 0;
01765 else
01766 return -1;
01767
01768
01769 }
01770
01771
01772
01773
01774
01775
01776
01777 time_t soap_read_date(Octstr* dateString)
01778 {
01779 int pos, count;
01780 struct universaltime stTime;
01781 long arTime[5];
01782
01783
01784 if (!dateString)
01785 return -1;
01786
01787 pos = count = 0;
01788
01789 while (count < 5 && pos < octstr_len(dateString) &&
01790 (pos = octstr_parse_long(&(arTime[count++]),dateString, pos,10)) && pos != -1)
01791 ++pos;
01792
01793 if (count < 5) {
01794
01795 debug("bb.soap.read_date",0,"read_date failed parsing the date value <%s>", octstr_get_cstr(dateString));
01796 return -1;
01797 }
01798
01799 stTime.day = arTime[0];
01800 stTime.month = arTime[1];
01801 stTime.year = arTime[2];
01802 stTime.hour = arTime[3];
01803 stTime.minute = arTime[4];
01804 stTime.second = 0;
01805 return date_convert_universal(&stTime);
01806 }
01807
01808
01809
01810
01811
01812
01813
01814 static Octstr* soap_write_date(time_t date)
01815 {
01816 struct tm date_parts;
01817 Octstr* out;
01818
01819 if (date < 0)
01820
01821
01822 return octstr_create("ERROR");
01823
01824
01825 gmtime_r(&date, &date_parts);
01826
01827 out = octstr_format("%d/%02d/%02d:%02d:%02d",
01828 date_parts.tm_year + 1900, date_parts.tm_mon + 1, date_parts.tm_mday, date_parts.tm_hour, date_parts.tm_min);
01829
01830
01831 if (out)
01832 return out;
01833 else
01834 return octstr_create("ERROR");
01835
01836 }
01837
01838
01839
01840
01841
01842
01843
01844
01845 int soap_server_start(SMSCConn *conn)
01846 {
01847 PrivData* privdata = conn->data;
01848
01849 debug("bb.soap.server_stop",0,"SOAP[%s]: Starting HTTP server", octstr_get_cstr(privdata->name));
01850
01851 if (http_open_port(privdata->port,privdata->ssl)) {
01852 return -1;
01853 }
01854
01855
01856
01857 privdata->soap_server = 1;
01858
01859 if ( (privdata->server_thread = gwthread_create(soap_server, conn)) == -1)
01860 {
01861 error(0, "SOAP[%s]: server_start failed to create server thread!", octstr_get_cstr(privdata->name));
01862 http_close_port(privdata->port);
01863 return -1;
01864 }
01865
01866
01867 return 0;
01868 }
01869
01870
01871
01872
01873
01874
01875 static void soap_server_stop(PrivData* privdata)
01876 {
01877
01878
01879 debug("bb.soap.server_stop",0,"SOAP[%s]: Stopping HTTP server", octstr_get_cstr(privdata->name));
01880
01881 privdata->soap_server = 0;
01882
01883
01884 http_close_port(privdata->port);
01885
01886 if (privdata->server_thread) {
01887 gwthread_wakeup(privdata->server_thread);
01888 gwthread_join(privdata->server_thread);
01889 privdata->server_thread = 0;
01890 }
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905 debug("bb.soap.server_stop",0,"SOAP[%s]: Done stopping HTTP server", octstr_get_cstr(privdata->name));
01906 }
01907
01908
01909
01910
01911
01912
01913
01914
01915 static ClientData* soap_create_client_data()
01916 {
01917
01918 ClientData *cd = gw_malloc(sizeof(ClientData));
01919
01920 cd->last_access = 0;
01921 cd->requests = 0;
01922 cd->caller = http_caller_create();
01923
01924 return cd;
01925 }
01926
01927
01928
01929
01930
01931
01932
01933 static void soap_client_init_query(PrivData* privdata, List* headers, Octstr* data, Msg* msg)
01934 {
01935 ClientData *cur_client = NULL;
01936 long index;
01937
01938
01939
01940 if (!privdata->soap_client)
01941 privdata->soap_client = gwlist_create();
01942
01943
01944 gwlist_lock(privdata->soap_client);
01945
01946
01947 for (index = gwlist_len(privdata->soap_client) - 1 ; index >= 0; --index) {
01948 cur_client = gwlist_get(privdata->soap_client, index);
01949 if (
01950 cur_client->last_access + CLIENT_BUSY_TIME < time(NULL)
01951 &&
01952 cur_client->requests < CLIENT_BUSY_LOAD
01953 ) {
01954 debug("bb.soap.init_query",0,"SOAP[%s]: init_query getting a client",octstr_get_cstr(privdata->name));
01955
01956
01957 gwlist_delete(privdata->soap_client, index, 1);
01958 break;
01959 }
01960 cur_client = NULL;
01961 }
01962
01963 if (!cur_client) {
01964 if (gwlist_len(privdata->soap_client) > MAX_SOAP_CLIENTS) {
01965 debug("bb.soap.init_query",0,"SOAP[%s]: init_query all clients are busy, getting the first client",octstr_get_cstr(privdata->name));
01966
01967
01968 cur_client = gwlist_extract_first(privdata->soap_client);
01969 } else {
01970
01971
01972 debug("bb.soap.init_query",0,"SOAP[%s]: init_query creates a new client",octstr_get_cstr(privdata->name));
01973 cur_client = soap_create_client_data();
01974 }
01975 }
01976
01977
01978 http_start_request(cur_client->caller, HTTP_METHOD_POST, privdata->uri, headers, data, 1, msg, NULL);
01979 cur_client->requests++;
01980 cur_client->last_access = time(NULL);
01981 gwlist_append(privdata->soap_client, cur_client);
01982 gwlist_unlock(privdata->soap_client);
01983 }
01984
01985
01986
01987
01988
01989
01990
01991 static void soap_destroy_client_data(void* data)
01992 {
01993 ClientData *cd = (ClientData*) data;
01994
01995
01996 if (cd->caller) {
01997 http_caller_signal_shutdown(cd->caller);
01998 http_caller_destroy(cd->caller);
01999 }
02000 }
02001
02002
02003
02004
02005
02006
02007
02008
02009 static ClientData* soap_client_have_response(List* client_list)
02010 {
02011 long index;
02012 ClientData* cd;
02013
02014 if (!client_list)
02015 return NULL;
02016
02017
02018 gwlist_lock(client_list);
02019
02020 for (index = gwlist_len(client_list) - 1; index >= 0; --index) {
02021 cd = gwlist_get(client_list,index);
02022 if (gwlist_len(cd->caller)) {
02023
02024 gwlist_unlock(client_list);
02025 return gwlist_get(client_list, index);
02026 }
02027 }
02028
02029 gwlist_unlock(client_list);
02030 return NULL;
02031 }
02032
02033
02034
02035
02036
02037
02038
02039
02040 static Octstr* soap_convert_token(Msg* msg, Octstr* name, PrivData* privdata)
02041
02042 {
02043 char buf[20];
02044 int index;
02045
02046 if ( (index=soap_lookup_function(name)) >= 0 )
02047 return soap_select_function(index, msg, privdata);
02048
02049
02050 #define INTEGER(fieldname) \
02051 if (!octstr_str_compare(name, #fieldname)) { \
02052 sprintf(buf,"%ld", p->fieldname); \
02053 return octstr_create(buf); \
02054 }
02055 #define INT64(fieldname) \
02056 if (!octstr_str_compare(name, #fieldname)) { \
02057 sprintf(buf,"%lld", p->fieldname); \
02058 return octstr_create(buf); \
02059 }
02060 #define OCTSTR(fieldname) \
02061 if (!octstr_str_compare(name, #fieldname)) \
02062 return octstr_duplicate(p->fieldname);
02063 #define UUID(fieldname)
02064 #define VOID(fieldname)
02065
02066 #define MSG(type, stmt) \
02067 case type: { struct type *p = &msg->type; stmt } break;
02068
02069 switch (msg->type) {
02070 #include "msg-decl.h"
02071 default:
02072
02073
02074 error(0, "SOAP: Internal error: unknown message type %d", msg->type);
02075 return NULL;
02076 }
02077
02078 error(0,"SOAP: soap_convert_token, can't find token named <%s>", octstr_get_cstr(name));
02079 return NULL;
02080 }
02081
02082
02083
02084
02085
02086
02087
02088 List* soap_create_map(Octstr* spec, long count, char* keywords[], char* types[], void* storage[])
02089 {
02090 List *parse_items, *out;
02091
02092 out = gwlist_create();
02093
02094
02095 parse_items = octstr_split(spec, octstr_imm("\n"));
02096
02097 while (gwlist_len(parse_items)) {
02098 ArgumentMap* map;
02099 int index;
02100 Octstr* temp = gwlist_extract_first(parse_items);
02101 List* item = octstr_split_words(temp);
02102
02103
02104
02105 if (gwlist_len(item) < 2) {
02106 debug("bb.soap.parse_create_map",0,"SOAP: broken spec file line <%s> in soap_create_map",
02107 octstr_get_cstr(temp));
02108 octstr_destroy(temp);
02109 gwlist_destroy(item, octstr_destroy_item);
02110 continue;
02111 }
02112
02113
02114 for (index = 0; index < count; ++index) {
02115 if (!octstr_str_compare(gwlist_get(item,0), keywords[index])) {
02116
02117 map = gw_malloc(sizeof(ArgumentMap));
02118 map->name = gwlist_extract_first(item);
02119 map->path = gwlist_extract_first(item);
02120 map->attribute = gwlist_extract_first(item);
02121 map->sscan_type = octstr_create(types[index]);
02122 map->store = storage[index];
02123 gwlist_append(out, map);
02124 break;
02125 }
02126 }
02127
02128
02129 gwlist_destroy(item, octstr_destroy_item);
02130 octstr_destroy(temp);
02131 }
02132
02133 gwlist_destroy(parse_items, octstr_destroy_item);
02134
02135 return out;
02136 }
02137
02138
02139
02140
02141
02142
02143 void soap_destroy_map(void *item)
02144 {
02145 ArgumentMap* map = item;
02146 octstr_destroy(map->name);
02147 octstr_destroy(map->path);
02148 octstr_destroy(map->attribute);
02149 octstr_destroy(map->sscan_type);
02150 gw_free(map);
02151 }
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162 Octstr* soap_fetch_xml_data(xmlNodePtr xml, Octstr* path)
02163 {
02164 Octstr *temp, *xml_path, *attr_name = NULL;
02165 List* path_elements;
02166 unsigned char c;
02167 xmlNodePtr parent, node;
02168 int index;
02169
02170
02171
02172 if (!octstr_len(path) || !xml)
02173 return NULL;
02174
02175
02176
02177 if (((c = octstr_get_char(path, 0)) == '"' || c == '\'') &&
02178 (octstr_get_char(path, octstr_len(path)-1) == c))
02179 return octstr_copy(path, 1, octstr_len(path) - 2);
02180
02181
02182 path_elements = octstr_split(path, octstr_imm(","));
02183 xml_path = gwlist_get(path_elements,0);
02184 if (gwlist_len(path_elements) > 1)
02185 attr_name = gwlist_get(path_elements,1);
02186 gwlist_destroy(path_elements, NULL);
02187
02188
02189 path_elements = octstr_split(xml_path, octstr_imm("/"));
02190
02191
02192 parent = NULL;
02193 node = xml;
02194 index = 0;
02195 while (index < gwlist_len(path_elements)) {
02196 int found = 0;
02197
02198 temp = gwlist_get(path_elements, index);
02199 do {
02200 if (!octstr_str_compare(temp,(char *)node->name)) {
02201
02202 if (!(node->xmlChildrenNode) && index < (gwlist_len(path_elements)-1)) {
02203
02204
02205 debug("bb.soap.fetch_xml_data",0,"SOAP: fetch_xml - error parsing XML, "
02206 "looking for <%s>, but element <%s> has no children",
02207 octstr_get_cstr(xml_path), octstr_get_cstr(temp));
02208 } else {
02209 ++index;
02210 parent = node;
02211 node = node->xmlChildrenNode;
02212 ++found;
02213 break;
02214 }
02215 }
02216
02217 } while ((node = node->next));
02218
02219 if (!found) {
02220
02221 node = parent;
02222 parent = node->parent;
02223 if (--index < 0)
02224
02225 break;
02226
02227 if (!(node = node->next))
02228
02229
02230
02231 break;
02232 }
02233 }
02234
02235
02236
02237
02238 if (index < gwlist_len(path_elements)) {
02239
02240 debug("bb.soap.map_xml_data",0,"SOAP: fetch_xml - path <%s> cannot be traveled in input XML",
02241 octstr_get_cstr(xml_path));
02242 gwlist_destroy(path_elements, octstr_destroy_item);
02243 octstr_destroy(xml_path);
02244 octstr_destroy(attr_name);
02245 return NULL;
02246 }
02247
02248
02249
02250
02251 if (attr_name) {
02252 xmlChar* content;
02253 content = xmlGetProp(parent, (xmlChar *)octstr_get_cstr(attr_name));
02254 if (content)
02255 temp = octstr_create((char *)content);
02256 else
02257 temp = octstr_create("");
02258 xmlFree(content);
02259 } else {
02260 xmlChar* content;
02261 content = xmlNodeGetContent(parent);
02262 if (content)
02263 temp = octstr_create((char *)content);
02264 else
02265 temp = octstr_create("");
02266 xmlFree(content);
02267 }
02268
02269 gwlist_destroy(path_elements, octstr_destroy_item);
02270 octstr_destroy(xml_path);
02271 octstr_destroy(attr_name);
02272
02273 return temp;
02274 }
02275
02276
02277
02278
02279
02280
02281
02282 int soap_map_xml_data(xmlNodePtr xml, List* maps)
02283 {
02284 int mapindex = 0, args = 0;
02285 xmlNodePtr node, parent;
02286
02287
02288 while (mapindex < gwlist_len(maps)) {
02289
02290 Octstr* temp;
02291
02292 int index = 0;
02293 ArgumentMap* map = gwlist_get(maps,mapindex);
02294
02295 List* path_elements = octstr_split(map->path, octstr_imm("/"));
02296
02297
02298 parent = NULL;
02299 node = xml;
02300 while (index < gwlist_len(path_elements)) {
02301 int found = 0;
02302
02303 temp = gwlist_get(path_elements, index);
02304 do {
02305 if (!octstr_str_compare(temp,(char *)node->name)) {
02306
02307 if (!(node->xmlChildrenNode) && index < (gwlist_len(path_elements)-1)) {
02308
02309
02310 debug("bb.soap.map_xml_data",0,"SOAP: error parsing XML, looking for <%s>, but element <%s> has no children",
02311 octstr_get_cstr(map->path), octstr_get_cstr(temp));
02312 } else {
02313 ++index;
02314 parent = node;
02315 node = node->xmlChildrenNode;
02316 ++found;
02317 break;
02318 }
02319 }
02320 } while ((node = node->next));
02321
02322 if (!found) {
02323
02324 node = parent;
02325 if (parent==NULL)
02326 return 0;
02327
02328 parent = node->parent;
02329 if (--index < 0)
02330
02331 break;
02332
02333 if (!(node = node->next))
02334
02335 break;
02336
02337 }
02338 }
02339
02340
02341 if (index < gwlist_len(path_elements)) {
02342
02343 debug("bb.soap.map_xml_data",0,"SOAP: didn't find element for keyword <%s> in XML data",
02344 octstr_get_cstr(map->name));
02345 gwlist_destroy(path_elements, octstr_destroy_item);
02346 ++mapindex;
02347 continue;
02348 }
02349
02350
02351 if (map->attribute) {
02352
02353
02354 xmlChar* content;
02355 content = xmlGetProp(parent, (xmlChar *)octstr_get_cstr(map->attribute));
02356 if (content)
02357 temp = octstr_create((char *)content);
02358 else
02359 temp = octstr_create("");
02360 xmlFree(content);
02361 } else {
02362
02363 xmlChar* content;
02364 content = xmlNodeGetContent(parent);
02365 if (content)
02366 temp = octstr_create((char *)content);
02367 else
02368
02369 temp = octstr_create("");
02370 xmlFree(content);
02371 }
02372
02373
02374 octstr_strip_blanks(temp);
02375 if (!octstr_str_compare(map->sscan_type,"%s")) {
02376
02377 strcpy(map->store,octstr_get_cstr(temp));
02378
02379 ++args;
02380 } else {
02381 if (!sscanf(octstr_get_cstr(temp), octstr_get_cstr(map->sscan_type), map->store)) {
02382 debug("bb.soap.map_xml_data",0,"SOAP: failed to scan content '%s' for '%s' in xml parsing",
02383 octstr_get_cstr(temp), octstr_get_cstr(map->sscan_type));
02384 } else {
02385 ++args;
02386 }
02387 }
02388
02389
02390
02391 octstr_destroy(temp);
02392 gwlist_destroy(path_elements, octstr_destroy_item);
02393 ++mapindex;
02394 }
02395 return args;
02396 }
02397
02398
02399
02400
02401
02402
02403
02404 long soap_release_dependences(Octstr* file_deps, List* lstmaps, Msg* msg, PrivData *privdata)
02405 {
02406 List *issues;
02407 long i, j, key_index, key_deps_index, map_index;
02408 int res, k;
02409 List *issue_items, *header_item;
02410 int key_func_index;
02411 ArgumentMap* map;
02412 Octstr *header, *key, *key_deps;
02413 Octstr *func_alias = NULL, *block;
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430 char* funcs[][5] = {
02431 {"text","binary","unicode","default"},
02432 {"set_iso","64_binary","hex_binary","unicode","default"}
02433 };
02434
02435
02436 issues = octstr_split(file_deps, octstr_imm(";"));
02437
02438 if (gwlist_len(issues) == 0) {
02439 error(0, "SOAP: soap_release_dependences, empty or broken 'deps' file");
02440 return -1;
02441 }
02442
02443 for (i=0; i<gwlist_len(issues); ++i)
02444 {
02445 block = gwlist_get(issues, i);
02446 octstr_strip_crlfs(block);
02447 octstr_strip_blanks(block);
02448
02449 issue_items = octstr_split(block, octstr_imm("\n"));
02450 if (gwlist_len(issue_items) < 2) {
02451 error(0, "SOAP: soap_release_dependences, broken file 'deps' can't find any definition for <key>");
02452 gwlist_destroy(issue_items, octstr_destroy_item);
02453 gwlist_destroy(issues, octstr_destroy_item);
02454 return -1;
02455 }
02456
02457
02458 header = gwlist_extract_first(issue_items);
02459 header_item = octstr_split_words(header);
02460 O_DESTROY(header);
02461
02462 if (gwlist_len(header_item) < 2) {
02463 error(0, "SOAP: soap_release_dependences, broken 'deps' file in <key> <key_deps> part");
02464 gwlist_destroy(header_item, octstr_destroy_item);
02465 gwlist_destroy(issue_items, octstr_destroy_item);
02466 gwlist_destroy(issues, octstr_destroy_item);
02467 return -1;
02468 }
02469
02470 key = gwlist_get(header_item, 0);
02471 key_deps = gwlist_get(header_item, 1);
02472 key_index = soap_get_index(lstmaps, key, 0);
02473 key_deps_index = soap_get_index(lstmaps, key_deps, 0);
02474
02475 if (key_index == -1 || key_deps_index == -1) {
02476 gwlist_destroy(header_item, octstr_destroy_item);
02477 gwlist_destroy(issue_items, octstr_destroy_item);
02478 gwlist_destroy(issues, octstr_destroy_item);
02479 return -1;
02480 }
02481
02482 map_index = soap_get_index(lstmaps, key_deps, 1);
02483 map = gwlist_get(lstmaps, map_index);
02484
02485
02486 for (j=0; j < gwlist_len(issue_items); ++j) {
02487
02488 Octstr *tmp = gwlist_get(issue_items, j);
02489 List *row = octstr_split_words(tmp);
02490
02491 if (!octstr_str_compare(gwlist_get(row, 0), map->store)) {
02492 func_alias = octstr_duplicate(gwlist_get(row, 1));
02493 gwlist_destroy(row, octstr_destroy_item);
02494 break;
02495 }
02496
02497 if (j==gwlist_len(issue_items)-1) {
02498 error(0, "SOAP: soap_release_dependences, \
02499 can't find function_alias for <%s> in 'deps' file, set default", (char*)map->store);
02500 func_alias = octstr_create(SPEC_DEFAULT);
02501 }
02502 gwlist_destroy(row, octstr_destroy_item);
02503 }
02504
02505 key_func_index = -1;
02506
02507 for (k=0; k < sizeof(funcs[key_index])/sizeof(funcs[key_index][0]); ++k)
02508 {
02509 if (!octstr_str_compare(func_alias, funcs[key_index][k])) {
02510 key_func_index = k;
02511 break;
02512 }
02513 }
02514 if (key_func_index==-1)
02515 error(0, "SOAP: soap_release_dependences, can't find function for alias <%s>", octstr_get_cstr(func_alias));
02516
02517 O_DESTROY(func_alias);
02518
02519 gwlist_destroy(header_item, octstr_destroy_item);
02520 gwlist_destroy(issue_items, octstr_destroy_item);
02521
02522
02523 if ((res=soap_process_deps(key_index, key_func_index, msg, privdata)) < 0)
02524 error(0, "SOAP: soap_release_dependences, error processing dependent value");
02525 }
02526 gwlist_destroy(issues, octstr_destroy_item);
02527
02528
02529 return 0;
02530 }
02531
02532
02533
02534
02535
02536 int soap_process_deps(int key_index, int key_func_ind, Msg* msg, PrivData *privdata)
02537 {
02538
02539 switch (key_index)
02540 {
02541 case 0:
02542 return soap_msgtype_deps(key_func_ind, msg);
02543 case 1:
02544 return soap_msgdata_deps(key_func_ind, msg, privdata);
02545 default:
02546 return -1;
02547 }
02548 return -1;
02549 }
02550
02551
02552
02553
02554
02555 int soap_msgtype_deps(int key_func_index, Msg* msg)
02556 {
02557
02558
02559
02560 switch (key_func_index)
02561 {
02562 case 0:
02563 msg->sms.coding = DC_7BIT;
02564 break;
02565 case 1:
02566 msg->sms.coding = DC_8BIT;
02567 break;
02568
02569 case 2:
02570 case 3:
02571 msg->sms.coding = DC_UCS2;
02572 break;
02573 default:
02574
02575 error(0, "SOAP: soap_msgtype_deps, unknown index %d", key_func_index);
02576 return -1;
02577 }
02578 return 0;
02579 }
02580
02581 int soap_msgdata_deps(int key_func_index, Msg* msg, PrivData *privdata)
02582 {
02583 int ret = 0;
02584
02585
02586
02587 switch (key_func_index)
02588 {
02589 case 0:
02590 msg->sms.charset = octstr_create("ISO-8859-1");
02591 break;
02592 case 1:
02593 octstr_base64_to_binary(msg->sms.msgdata);
02594 break;
02595 case 2:
02596 octstr_hex_to_binary(msg->sms.msgdata);
02597 break;
02598
02599 case 3:
02600 case 4:
02601
02602 if (!octstr_case_compare(privdata->alt_charset, octstr_imm("UCS-2"))) {
02603 debug("bb.soap.msgdata_deps",0,"SOAP[%s]: converting from %s to UCS-2BE",
02604 octstr_get_cstr(privdata->name), octstr_get_cstr(privdata->alt_charset));
02605 ret = charset_convert(msg->sms.msgdata, octstr_get_cstr(privdata->alt_charset), "UCS-2BE");
02606
02607 if (ret == -1) {
02608
02609 error(2,"SOAP[%s]: Error converting MO data from %s to unicode",
02610 octstr_get_cstr(privdata->name), octstr_get_cstr(privdata->alt_charset));
02611 }
02612 }
02613 else if (ret != 0) {
02614 debug("bb.soap.parse_mo",1,"SOAP[%s]: charset_convert made %d irreversable transformations",
02615 octstr_get_cstr(privdata->name), ret);
02616 }
02617 msg->sms.charset = octstr_create("UCS-2");
02618
02619 debug("bb.soap.parse_mo",0,"SOAP[%s]: message decoded -", octstr_get_cstr(privdata->name));
02620 octstr_dump(msg->sms.msgdata, 0);
02621 break;
02622
02623 default:
02624
02625
02626 error(0, "SOAP: soap_msgdata_deps, unknown index %d", key_func_index);
02627 return -1;
02628 }
02629 return 0;
02630 }
02631
02632
02633
02634
02635
02636
02637 int soap_lookup_function(Octstr* funcname)
02638 {
02639 int i;
02640
02641
02642 char *aliasis[] = {
02643 "bouyg_content", "mobitai_content",
02644 "o2o_msgdata", "msgdata",
02645 "o2o_validity30", "mobitai_validity_date", "bouyg_validity",
02646 "o2o_date", "mobitai_date", "rand",
02647 "o2o_dlrmask_smsc_yn", "o2o_dlrmask_success_01"
02648 };
02649
02650 for (i=0; i<sizeof(aliasis)/sizeof(aliasis[0]); ++i)
02651 {
02652 if (!octstr_str_compare(funcname, aliasis[i]))
02653 return i;
02654 }
02655 return -1;
02656 }
02657
02658
02659
02660
02661
02662
02663 Octstr* soap_select_function(int index, Msg* msg, PrivData* privdata)
02664 {
02665
02666 switch (index)
02667 {
02668 case 0:
02669 return soap_bouyg_content_attribute(msg);
02670 case 1:
02671 return soap_mobitai_content_attribute(msg);
02672 case 2:
02673 return soap_o2o_msgdata_attribute(msg, privdata);
02674 case 3:
02675 return soap_msgdata_attribute(msg, privdata);
02676 case 4:
02677 return soap_o2o_validity30_attribute(msg);
02678 case 5:
02679 return soap_mobitai_validity_date_attribute(msg);
02680 case 6:
02681 return soap_bouyg_validity_attribute(msg);
02682 case 7:
02683 return soap_o2o_date_attribute(msg);
02684 case 8:
02685 return soap_mobitai_date_attribute(msg);
02686 case 9:
02687 return soap_rand_attribute(msg);
02688 case 10:
02689 return soap_o2o_dlrmask_smsc_yn_attribute(msg);
02690 case 11:
02691 return soap_o2o_dlrmask_success_01_attribute(msg);
02692 default:
02693 error(0,"SOAP: soap_select_function can't find function");
02694 return NULL;
02695 }
02696 }
02697
02698
02699
02700 Octstr* soap_bouyg_content_attribute(Msg* msg)
02701 {
02702
02703 if (msg->sms.coding == DC_8BIT)
02704 return octstr_create("D");
02705 else
02706 return octstr_create("A");
02707 }
02708
02709 Octstr* soap_mobitai_content_attribute(Msg* msg)
02710 {
02711 if (msg->sms.coding == DC_8BIT)
02712 return octstr_create("binary");
02713 else
02714 return octstr_create("text");
02715
02716 }
02717
02718 Octstr* soap_o2o_msgdata_attribute(Msg* msg, PrivData *privdata)
02719 {
02720 Octstr *data, *res, *udhres;
02721 int ret;
02722
02723 data = octstr_duplicate(msg->sms.msgdata);
02724
02725 if (msg->sms.coding == DC_8BIT) {
02726 debug("bb.soap.o2o_msgdata_attribute",0,"SOAP: base 64 encoding");
02727 octstr_binary_to_base64(data);
02728 res = octstr_format("<Control_Data>%S</Control_Data>", data);
02729
02730 if (octstr_len(msg->sms.udhdata) > 0) {
02731 O_DESTROY(data);
02732 data = octstr_duplicate(msg->sms.udhdata);
02733 debug("bb.soap.o2o_msgdata_attribute",0,"SOAP: UDH base 64 encoding");
02734 octstr_binary_to_base64(data);
02735 udhres = octstr_format("<UDH>%S</UDH>", data);
02736 octstr_append(res, udhres);
02737 O_DESTROY(udhres);
02738 }
02739 else {
02740 error(0, "SOAP: o2o_msgdata_attribute, UDH not defined");
02741 udhres = octstr_create("<UDH></UDH>");
02742 octstr_append(res, udhres);
02743 O_DESTROY(udhres);
02744 }
02745 O_DESTROY(data);
02746 return res;
02747 }
02748 else if (msg->sms.coding == DC_7BIT || msg->sms.coding == DC_UNDEF) {
02749
02750 debug("bb.soap.o2o_msgdata_attribute", 0, "SOAP: converting from UTF-8 to %s", octstr_get_cstr(privdata->alt_charset));
02751 ret = charset_convert(data, "UTF-8", octstr_get_cstr(privdata->alt_charset));
02752 if (ret == -1) {
02753 error(0,"SOAP: soap_o2o_msgdata_attribute, charset_convert failed");
02754 octstr_dump(msg->sms.msgdata, 0);
02755 O_DESTROY(data);
02756 return NULL;
02757 }
02758 debug("bb.soap.o2o_msgdata_attribute",0,"SOAP: converting to HTML entities");
02759 octstr_convert_to_html_entities(data);
02760 res = octstr_format("<Message_Text>%S</Message_Text>", data);
02761 O_DESTROY(data);
02762 return res;
02763 }
02764 else if (msg->sms.coding == DC_UCS2) {
02765
02766 debug("bb.soap.o2o_msgdata_attribute", 0, "converting from USC-2 to %s", octstr_get_cstr(privdata->alt_charset));
02767 ret = charset_convert(msg->sms.msgdata, "UCS-2BE", octstr_get_cstr(privdata->alt_charset));
02768 if (ret == -1) {
02769 error(0,"SOAP: soap_o2o_msgdata_attribute, charset_convert failed");
02770
02771 octstr_dump(msg->sms.msgdata, 0);
02772 O_DESTROY(data);
02773 return NULL;
02774 }
02775 res = octstr_format("<Message_Text>%s</Message_Text>", data);
02776 O_DESTROY(data);
02777 return res;
02778 }
02779
02780 else {
02781 error(0,"SOAP: soap_o2o_msgdata_attribute, unknown coding: %ld", msg->sms.coding);
02782 O_DESTROY(data);
02783 return NULL;
02784
02785 }
02786 }
02787
02788
02789 Octstr* soap_msgdata_attribute(Msg* msg, PrivData* privdata)
02790 {
02791 Octstr *data, *udhdata;
02792 int ret;
02793
02794
02795 data = octstr_duplicate(msg->sms.msgdata);
02796
02797 if (msg->sms.coding == DC_8BIT) {
02798 udhdata = octstr_duplicate(msg->sms.udhdata);
02799 octstr_append(udhdata, data);
02800 octstr_binary_to_hex(udhdata, 1);
02801 O_DESTROY(data);
02802 return udhdata;
02803 }
02804 else if (msg->sms.coding == DC_7BIT || msg->sms.coding == DC_UNDEF) {
02805
02806 debug("bb.soap.msgdata_attribute", 0, "SOAP: converting from UTF-8 to %s", octstr_get_cstr(privdata->alt_charset));
02807 ret = charset_convert(data, "UTF-8", octstr_get_cstr(privdata->alt_charset));
02808 if (ret == -1) {
02809 error(0,"SOAP: soap_msgdata_attribute, charset_convert failed");
02810 octstr_dump(msg->sms.msgdata, 0);
02811 O_DESTROY(data);
02812 return NULL;
02813 }
02814 debug("bb.soap.msgdata_attribute",0,"SOAP: converting to HTML entities");
02815 octstr_convert_to_html_entities(data);
02816 return data;
02817 }
02818 else if (msg->sms.coding == DC_UCS2) {
02819
02820 debug("bb.soap.msgdata_attribute", 0, "converting from USC-2 to %s", octstr_get_cstr(privdata->alt_charset));
02821 ret = charset_convert(data, "UCS-2BE", octstr_get_cstr(privdata->alt_charset));
02822 if (ret == -1) {
02823 error(0,"SOAP: soap_msgdata_attribute, charset_convert failed");
02824
02825 octstr_dump(data, 0);
02826 O_DESTROY(data);
02827 return NULL;
02828 }
02829 return data;
02830 }
02831 else {
02832 error(0,"SOAP: soap_msgdata_attribute, unknown coding: %ld", msg->sms.coding);
02833 O_DESTROY(data);
02834 return NULL;
02835 }
02836 }
02837
02838
02839 Octstr* soap_o2o_validity30_attribute(Msg* msg)
02840 {
02841 return octstr_format("%ld",(msg->sms.validity != SMS_PARAM_UNDEFINED ?
02842 msg->sms.validity : SOAP_DEFAULT_VALIDITY) / 30);
02843 }
02844
02845
02846 Octstr* soap_mobitai_validity_date_attribute(Msg* msg)
02847 {
02848 return date_create_iso(msg->sms.time+(60*msg->sms.validity));
02849 }
02850
02851
02852 Octstr* soap_bouyg_validity_attribute(Msg* msg)
02853 {
02854 if(msg->sms.validity >= 0)
02855 return octstr_format("%d", 60*msg->sms.validity);
02856 else
02857 return octstr_format("%d", 0);
02858 }
02859
02860 Octstr* soap_o2o_date_attribute(Msg* msg)
02861 {
02862 return soap_write_date(msg->sms.time);
02863 }
02864
02865
02866
02867 Octstr* soap_mobitai_date_attribute(Msg* msg)
02868 {
02869 return date_create_iso(msg->sms.time);
02870 }
02871
02872 Octstr* soap_rand_attribute(Msg* msg)
02873 {
02874 return octstr_format("%d",gw_rand());
02875 }
02876
02877
02878 Octstr* soap_o2o_dlrmask_smsc_yn_attribute(Msg* msg)
02879 {
02880 return octstr_create(DLR_IS_ENABLED_SMSC(msg->sms.dlr_mask) ? "Y" : "N");
02881 }
02882
02883
02884 Octstr* soap_o2o_dlrmask_success_01_attribute(Msg* msg)
02885 {
02886 return octstr_create( DLR_IS_SUCCESS(msg->sms.dlr_mask) ? "0" : "1");
02887 }
02888
02889
02890
02891
02892
02893 int soap_get_index(List* where, Octstr* key, int map_index)
02894 {
02895 int i, j;
02896 ArgumentMap* map;
02897
02898
02899
02900 char* funcs_deps[] = {
02901 "msgtype", "msgdata"
02902 };
02903
02904 for (i=0; i < gwlist_len(where); ++i) {
02905 map = gwlist_get(where, i);
02906 if (!octstr_compare(map->name, key)) {
02907 if (map_index==1)
02908 return i;
02909
02910 for (j=0; j < sizeof(funcs_deps)/sizeof(funcs_deps[0]); ++j) {
02911 if (!octstr_str_compare(map->name, funcs_deps[j]))
02912 return j;
02913 }
02914 }
02915 }
02916 error(0, "SOAP: soap_get_index, broken 'deps' file, can't find key <%s> ", octstr_get_cstr(key));
02917 return -1;
02918 }
02919
02920
See file LICENSE for details about the license agreement for using,
modifying, copying or deriving work from this software.