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 "smscconn.h"
00123 #include "smscconn_p.h"
00124 #include "bb_smscconn_cb.h"
00125 #include "msg.h"
00126 #include "sms.h"
00127 #include "dlr.h"
00128 #include "urltrans.h"
00129
00130 #define DEFAULT_CHARSET "UTF-8"
00131
00132 typedef struct conndata {
00133 HTTPCaller *http_ref;
00134 long receive_thread;
00135 long send_cb_thread;
00136 int shutdown;
00137 int port;
00138 Octstr *allow_ip;
00139 Octstr *send_url;
00140 Octstr *dlr_url;
00141 long open_sends;
00142 Octstr *username;
00143 Octstr *password;
00144 Octstr *system_id;
00145 int no_sender;
00146 int no_coding;
00147 int no_sep;
00148 Octstr *proxy;
00149 Octstr *alt_charset;
00150
00151
00152
00153
00154
00155 regex_t *success_regex;
00156 regex_t *permfail_regex;
00157 regex_t *tempfail_regex;
00158
00159
00160 void (*send_sms) (SMSCConn *conn, Msg *msg);
00161 void (*parse_reply) (SMSCConn *conn, Msg *msg, int status,
00162 List *headers, Octstr *body);
00163 void (*receive_sms) (SMSCConn *conn, HTTPClient *client,
00164 List *headers, Octstr *body, List *cgivars);
00165 } ConnData;
00166
00167
00168 static void conndata_destroy(ConnData *conndata)
00169 {
00170 if (conndata == NULL)
00171 return;
00172 if (conndata->http_ref)
00173 http_caller_destroy(conndata->http_ref);
00174 if (conndata->success_regex)
00175 gw_regex_destroy(conndata->success_regex);
00176 if (conndata->permfail_regex)
00177 gw_regex_destroy(conndata->permfail_regex);
00178 if (conndata->tempfail_regex)
00179 gw_regex_destroy(conndata->tempfail_regex);
00180 octstr_destroy(conndata->allow_ip);
00181 octstr_destroy(conndata->send_url);
00182 octstr_destroy(conndata->dlr_url);
00183 octstr_destroy(conndata->username);
00184 octstr_destroy(conndata->password);
00185 octstr_destroy(conndata->proxy);
00186 octstr_destroy(conndata->system_id);
00187 octstr_destroy(conndata->alt_charset);
00188
00189 gw_free(conndata);
00190 }
00191
00192
00193
00194
00195
00196 static void httpsmsc_receiver(void *arg)
00197 {
00198 SMSCConn *conn = arg;
00199 ConnData *conndata = conn->data;
00200 HTTPClient *client;
00201 Octstr *ip, *url, *body;
00202 List *headers, *cgivars;
00203
00204 ip = url = body = NULL;
00205 headers = cgivars = NULL;
00206
00207
00208 log_thread_to(conn->log_idx);
00209
00210 while (conndata->shutdown == 0) {
00211
00212
00213
00214 client = http_accept_request(conndata->port, &ip, &url,
00215 &headers, &body, &cgivars);
00216 if (client == NULL)
00217 break;
00218
00219 debug("smsc.http", 0, "HTTP[%s]: Got request `%s'",
00220 octstr_get_cstr(conn->id), octstr_get_cstr(url));
00221
00222 if (connect_denied(conndata->allow_ip, ip)) {
00223 info(0, "HTTP[%s]: Connection `%s' tried from denied "
00224 "host %s, ignored", octstr_get_cstr(conn->id),
00225 octstr_get_cstr(url), octstr_get_cstr(ip));
00226 http_close_client(client);
00227 } else
00228 conndata->receive_sms(conn, client, headers, body, cgivars);
00229
00230 debug("smsc.http", 0, "HTTP[%s]: Destroying client information",
00231 octstr_get_cstr(conn->id));
00232 octstr_destroy(url);
00233 octstr_destroy(ip);
00234 octstr_destroy(body);
00235 http_destroy_headers(headers);
00236 http_destroy_cgiargs(cgivars);
00237 }
00238 debug("smsc.http", 0, "HTTP[%s]: httpsmsc_receiver dying",
00239 octstr_get_cstr(conn->id));
00240
00241 conndata->shutdown = 1;
00242 http_close_port(conndata->port);
00243
00244
00245 if (conndata->open_sends == 0)
00246 http_caller_signal_shutdown(conndata->http_ref);
00247 }
00248
00249
00250
00251
00252
00253 static void httpsmsc_send_cb(void *arg)
00254 {
00255 SMSCConn *conn = arg;
00256 ConnData *conndata = conn->data;
00257 Msg *msg;
00258 int status;
00259 List *headers;
00260 Octstr *final_url, *body;
00261
00262
00263 log_thread_to(conn->log_idx);
00264
00265 while (conndata->shutdown == 0 || conndata->open_sends) {
00266
00267 msg = http_receive_result(conndata->http_ref, &status,
00268 &final_url, &headers, &body);
00269
00270 if (msg == NULL)
00271 break;
00272
00273
00274
00275
00276 if (status == -1 && conndata->shutdown == 0) {
00277 error(0, "HTTP[%s]: Couldn't connect to SMS center "
00278 "(retrying in %ld seconds).",
00279 octstr_get_cstr(conn->id), conn->reconnect_delay);
00280 conn->status = SMSCCONN_RECONNECTING;
00281 gwthread_sleep(conn->reconnect_delay);
00282 debug("smsc.http.kannel", 0, "HTTP[%s]: Re-sending request",
00283 octstr_get_cstr(conn->id));
00284 conndata->send_sms(conn, msg);
00285 continue;
00286 }
00287
00288 else if (status == -1 && conndata->shutdown == 1) {
00289 }
00290
00291 else {
00292
00293 if (status && conn->status != SMSCCONN_ACTIVE) {
00294 conn->status = SMSCCONN_ACTIVE;
00295 time(&conn->connect_time);
00296 }
00297 conndata->parse_reply(conn, msg, status, headers, body);
00298 }
00299
00300 conndata->open_sends--;
00301
00302 http_destroy_headers(headers);
00303 octstr_destroy(final_url);
00304 octstr_destroy(body);
00305 }
00306 debug("smsc.http", 0, "HTTP[%s]: httpsmsc_send_cb dying",
00307 octstr_get_cstr(conn->id));
00308 conndata->shutdown = 1;
00309
00310 if (conndata->open_sends) {
00311 warning(0, "HTTP[%s]: Shutdown while <%ld> requests are pending.",
00312 octstr_get_cstr(conn->id), conndata->open_sends);
00313 }
00314
00315 gwthread_join(conndata->receive_thread);
00316
00317 conn->data = NULL;
00318 conndata_destroy(conndata);
00319
00320 conn->status = SMSCCONN_DEAD;
00321 bb_smscconn_killed();
00322 }
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380 enum { HEX_NOT_UPPERCASE = 0 };
00381
00382
00383 static void kannel_send_sms(SMSCConn *conn, Msg *sms)
00384 {
00385 ConnData *conndata = conn->data;
00386 Octstr *url;
00387 List *headers;
00388
00389 if (!conndata->no_sep) {
00390 url = octstr_format("%S?"
00391 "username=%E&password=%E&to=%E&text=%E",
00392 conndata->send_url,
00393 conndata->username, conndata->password,
00394 sms->sms.receiver, sms->sms.msgdata);
00395 } else {
00396 octstr_binary_to_hex(sms->sms.msgdata, HEX_NOT_UPPERCASE);
00397 url = octstr_format("%S?"
00398 "username=%E&password=%E&to=%E&text=%S",
00399 conndata->send_url,
00400 conndata->username, conndata->password,
00401 sms->sms.receiver,
00402 sms->sms.msgdata);
00403 }
00404
00405 if (octstr_len(sms->sms.udhdata)) {
00406 if (!conndata->no_sep) {
00407 octstr_format_append(url, "&udh=%E", sms->sms.udhdata);
00408 } else {
00409 octstr_binary_to_hex(sms->sms.udhdata, HEX_NOT_UPPERCASE);
00410 octstr_format_append(url, "&udh=%S", sms->sms.udhdata);
00411 }
00412 }
00413
00414 if (!conndata->no_sender)
00415 octstr_format_append(url, "&from=%E", sms->sms.sender);
00416 if (sms->sms.mclass != MC_UNDEF)
00417 octstr_format_append(url, "&mclass=%d", sms->sms.mclass);
00418 if (!conndata->no_coding && sms->sms.coding != DC_UNDEF)
00419 octstr_format_append(url, "&coding=%d", sms->sms.coding);
00420
00421
00422
00423
00424
00425
00426
00427
00428 if (sms->sms.coding == DC_7BIT)
00429 octstr_append_cstr(url, "&charset=UTF-8");
00430 else if (sms->sms.coding == DC_UCS2)
00431 octstr_append_cstr(url, "&charset=UTF-16BE");
00432
00433 if (sms->sms.mwi != MWI_UNDEF)
00434 octstr_format_append(url, "&mwi=%d", sms->sms.mwi);
00435 if (sms->sms.account)
00436 octstr_format_append(url, "&account=%E:%E", sms->sms.service, sms->sms.account);
00437 if (sms->sms.binfo)
00438 octstr_format_append(url, "&binfo=%S", sms->sms.binfo);
00439 if (sms->sms.smsc_id)
00440 octstr_format_append(url, "&smsc=%S", sms->sms.smsc_id);
00441 if (sms->sms.dlr_url) {
00442 if (conndata->dlr_url) {
00443 char id[UUID_STR_LEN + 1];
00444 Octstr *mid;
00445
00446
00447 uuid_unparse(sms->sms.id, id);
00448 mid = octstr_create(id);
00449
00450 octstr_format_append(url, "&dlr-url=%E", conndata->dlr_url);
00451
00452
00453
00454 octstr_format_append(url, "%E%E%E%E%E",
00455 octstr_imm("&dlr-url="), sms->sms.dlr_url,
00456 octstr_imm("&dlr-mask=%d"),
00457 octstr_imm("&dlr-mid="), mid);
00458
00459 octstr_destroy(mid);
00460 } else
00461 octstr_format_append(url, "&dlr-url=%E", sms->sms.dlr_url);
00462 }
00463 if (sms->sms.dlr_mask != DLR_UNDEFINED && sms->sms.dlr_mask != DLR_NOTHING)
00464 octstr_format_append(url, "&dlr-mask=%d", sms->sms.dlr_mask);
00465
00466 headers = gwlist_create();
00467 debug("smsc.http.kannel", 0, "HTTP[%s]: Start request",
00468 octstr_get_cstr(conn->id));
00469 http_start_request(conndata->http_ref, HTTP_METHOD_GET, url, headers,
00470 NULL, 0, sms, NULL);
00471
00472 octstr_destroy(url);
00473 http_destroy_headers(headers);
00474 }
00475
00476 static void kannel_parse_reply(SMSCConn *conn, Msg *msg, int status,
00477 List *headers, Octstr *body)
00478 {
00479
00480
00481
00482
00483 if ((status == HTTP_OK || status == HTTP_ACCEPTED)
00484 && (octstr_case_compare(body, octstr_imm("0: Accepted for delivery")) == 0 ||
00485 octstr_case_compare(body, octstr_imm("Sent.")) == 0 ||
00486 octstr_case_compare(body, octstr_imm("Ok.")) == 0 ||
00487 octstr_ncompare(body, octstr_imm("Result: OK"),10) == 0)) {
00488 char id[UUID_STR_LEN + 1];
00489 Octstr *mid;
00490
00491
00492 uuid_unparse(msg->sms.id, id);
00493 mid = octstr_create(id);
00494
00495
00496 if (DLR_IS_ENABLED_DEVICE(msg->sms.dlr_mask))
00497 dlr_add(conn->id, mid, msg);
00498
00499 octstr_destroy(mid);
00500
00501 bb_smscconn_sent(conn, msg, NULL);
00502 } else {
00503 bb_smscconn_send_failed(conn, msg,
00504 SMSCCONN_FAILED_MALFORMED, octstr_duplicate(body));
00505 }
00506 }
00507
00508
00509 static void kannel_receive_sms(SMSCConn *conn, HTTPClient *client,
00510 List *headers, Octstr *body, List *cgivars)
00511 {
00512 ConnData *conndata = conn->data;
00513 Octstr *user, *pass, *from, *to, *text, *udh, *account, *binfo;
00514 Octstr *dlrurl, *dlrmid;
00515 Octstr *tmp_string, *retmsg;
00516 int mclass, mwi, coding, validity, deferred, dlrmask;
00517 List *reply_headers;
00518 int ret;
00519
00520 mclass = mwi = coding = validity =
00521 deferred = dlrmask = SMS_PARAM_UNDEFINED;
00522
00523 user = http_cgi_variable(cgivars, "username");
00524 pass = http_cgi_variable(cgivars, "password");
00525 from = http_cgi_variable(cgivars, "from");
00526 to = http_cgi_variable(cgivars, "to");
00527 text = http_cgi_variable(cgivars, "text");
00528 udh = http_cgi_variable(cgivars, "udh");
00529 account = http_cgi_variable(cgivars, "account");
00530 binfo = http_cgi_variable(cgivars, "binfo");
00531 dlrurl = http_cgi_variable(cgivars, "dlr-url");
00532 dlrmid = http_cgi_variable(cgivars, "dlr-mid");
00533 tmp_string = http_cgi_variable(cgivars, "flash");
00534 if (tmp_string) {
00535 sscanf(octstr_get_cstr(tmp_string),"%d", &mclass);
00536 }
00537 tmp_string = http_cgi_variable(cgivars, "mclass");
00538 if (tmp_string) {
00539 sscanf(octstr_get_cstr(tmp_string),"%d", &mclass);
00540 }
00541 tmp_string = http_cgi_variable(cgivars, "mwi");
00542 if (tmp_string) {
00543 sscanf(octstr_get_cstr(tmp_string),"%d", &mwi);
00544 }
00545 tmp_string = http_cgi_variable(cgivars, "coding");
00546 if (tmp_string) {
00547 sscanf(octstr_get_cstr(tmp_string),"%d", &coding);
00548 }
00549 tmp_string = http_cgi_variable(cgivars, "validity");
00550 if (tmp_string) {
00551 sscanf(octstr_get_cstr(tmp_string),"%d", &validity);
00552 }
00553 tmp_string = http_cgi_variable(cgivars, "deferred");
00554 if (tmp_string) {
00555 sscanf(octstr_get_cstr(tmp_string),"%d", &deferred);
00556 }
00557 tmp_string = http_cgi_variable(cgivars, "dlr-mask");
00558 if (tmp_string) {
00559 sscanf(octstr_get_cstr(tmp_string),"%d", &dlrmask);
00560 }
00561 debug("smsc.http.kannel", 0, "HTTP[%s]: Received an HTTP request",
00562 octstr_get_cstr(conn->id));
00563
00564 if (user == NULL || pass == NULL ||
00565 octstr_compare(user, conndata->username) != 0 ||
00566 octstr_compare(pass, conndata->password) != 0) {
00567
00568 error(0, "HTTP[%s]: Authorization failure",
00569 octstr_get_cstr(conn->id));
00570 retmsg = octstr_create("Authorization failed for sendsms");
00571 }
00572 else if (dlrurl != NULL && dlrmask != 0 && dlrmid != NULL) {
00573
00574 Msg *dlrmsg;
00575
00576 dlrmsg = dlr_find(conn->id,
00577 dlrmid,
00578 to,
00579 dlrmask);
00580
00581 if (dlrmsg != NULL) {
00582 dlrmsg->sms.sms_type = report_mo;
00583
00584 debug("smsc.http.kannel", 0, "HTTP[%s]: Received DLR for DLR-URL <%s>",
00585 octstr_get_cstr(conn->id), octstr_get_cstr(dlrmsg->sms.dlr_url));
00586
00587 ret = bb_smscconn_receive(conn, dlrmsg);
00588 if (ret == -1)
00589 retmsg = octstr_create("Not accepted");
00590 else
00591 retmsg = octstr_create("Sent.");
00592 } else {
00593 error(0,"HTTP[%s]: Got DLR but could not find message or was not interested "
00594 "in it id<%s> dst<%s>, type<%d>",
00595 octstr_get_cstr(conn->id), octstr_get_cstr(dlrmid),
00596 octstr_get_cstr(to), dlrmask);
00597 retmsg = octstr_create("Unknown DLR, not accepted");
00598 }
00599 }
00600 else if (from == NULL || to == NULL || text == NULL) {
00601
00602 error(0, "HTTP[%s]: Insufficient args",
00603 octstr_get_cstr(conn->id));
00604 retmsg = octstr_create("Insufficient args, rejected");
00605 }
00606 else if (udh != NULL && (octstr_len(udh) != octstr_get_char(udh, 0) + 1)) {
00607 error(0, "HTTP[%s]: UDH field misformed, rejected",
00608 octstr_get_cstr(conn->id));
00609 retmsg = octstr_create("UDH field misformed, rejected");
00610 }
00611 else if (udh != NULL && octstr_len(udh) > MAX_SMS_OCTETS) {
00612 error(0, "HTTP[%s]: UDH field is too long, rejected",
00613 octstr_get_cstr(conn->id));
00614 retmsg = octstr_create("UDH field is too long, rejected");
00615 }
00616 else {
00617
00618 Msg *msg;
00619 msg = msg_create(sms);
00620
00621 debug("smsc.http.kannel", 0, "HTTP[%s]: Constructing new SMS",
00622 octstr_get_cstr(conn->id));
00623
00624 msg->sms.service = octstr_duplicate(user);
00625 msg->sms.sender = octstr_duplicate(from);
00626 msg->sms.receiver = octstr_duplicate(to);
00627 msg->sms.msgdata = octstr_duplicate(text);
00628 msg->sms.udhdata = octstr_duplicate(udh);
00629
00630 msg->sms.smsc_id = octstr_duplicate(conn->id);
00631 msg->sms.time = time(NULL);
00632 msg->sms.mclass = mclass;
00633 msg->sms.mwi = mwi;
00634 msg->sms.coding = coding;
00635 msg->sms.validity = validity;
00636 msg->sms.deferred = deferred;
00637 msg->sms.account = octstr_duplicate(account);
00638 msg->sms.binfo = octstr_duplicate(binfo);
00639 ret = bb_smscconn_receive(conn, msg);
00640 if (ret == -1)
00641 retmsg = octstr_create("Not accepted");
00642 else
00643 retmsg = octstr_create("Sent.");
00644 }
00645
00646 reply_headers = gwlist_create();
00647 http_header_add(reply_headers, "Content-Type", "text/plain");
00648 debug("smsc.http.kannel", 0, "HTTP[%s]: Sending reply",
00649 octstr_get_cstr(conn->id));
00650 http_send_reply(client, HTTP_ACCEPTED, reply_headers, retmsg);
00651
00652 octstr_destroy(retmsg);
00653 http_destroy_headers(reply_headers);
00654 }
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665 static void clickatell_send_sms(SMSCConn *conn, Msg *sms)
00666 {
00667 ConnData *conndata = conn->data;
00668 Octstr *url, *os;
00669 char id[UUID_STR_LEN + 1];
00670 List *headers;
00671
00672
00673 url = octstr_format("%S/sendmsg?to=%E&from=%E&api_id=%E&user=%E&password=%E",
00674 conndata->send_url, sms->sms.receiver, sms->sms.sender,
00675 conndata->system_id, conndata->username, conndata->password);
00676
00677
00678 uuid_unparse(sms->sms.id, id);
00679 os = octstr_create(id);
00680 octstr_replace(os, octstr_imm("-"), octstr_imm(""));
00681 octstr_format_append(url, "&cliMsgId=%E", os);
00682 octstr_destroy(os);
00683
00684
00685 if (octstr_len(sms->sms.udhdata)) {
00686 octstr_format_append(url, "&data=%H", sms->sms.msgdata);
00687 octstr_format_append(url, "&udh=%H", sms->sms.udhdata);
00688 } else {
00689 octstr_format_append(url, "&text=%E", sms->sms.msgdata);
00690 if (conndata->alt_charset) {
00691 octstr_format_append(url, "&charset=%E", conndata->alt_charset);
00692 } else {
00693 octstr_append_cstr(url, "&charset=UTF-8");
00694 }
00695 }
00696
00697 if (DLR_IS_ENABLED_DEVICE(sms->sms.dlr_mask))
00698 octstr_format_append(url, "&callback=3&deliv_ack=1");
00699
00700 headers = http_create_empty_headers();
00701 debug("smsc.http.clickatell", 0, "HTTP[%s]: Sending request <%s>",
00702 octstr_get_cstr(conn->id), octstr_get_cstr(url));
00703
00704
00705
00706
00707
00708 http_start_request(conndata->http_ref, HTTP_METHOD_GET, url, headers, NULL, 0, sms, NULL);
00709
00710 octstr_destroy(url);
00711 http_destroy_headers(headers);
00712 }
00713
00714
00715
00716
00717
00718
00719
00720 static Dict *clickatell_parse_body(Octstr *body)
00721 {
00722 Dict *param = NULL;
00723 List *words = NULL;
00724 long len;
00725 Octstr *word, *value;
00726
00727 words = octstr_split_words(body);
00728 if ((len = gwlist_len(words)) > 1) {
00729 word = gwlist_extract_first(words);
00730 if (octstr_compare(word, octstr_imm("ID:")) == 0) {
00731 value = gwlist_extract_first(words);
00732 param = dict_create(4, (void(*)(void *)) octstr_destroy);
00733 dict_put(param, octstr_imm("ID"), value);
00734 } else if (octstr_compare(word, octstr_imm("ERR:")) == 0) {
00735 value = gwlist_extract_first(words);
00736 param = dict_create(4, (void(*)(void *)) octstr_destroy);
00737 dict_put(param, octstr_imm("ERR"), value);
00738 }
00739 octstr_destroy(word);
00740 }
00741 gwlist_destroy(words, (void(*)(void *)) octstr_destroy);
00742
00743 return param;
00744 }
00745
00746
00747 static void clickatell_parse_reply(SMSCConn *conn, Msg *msg, int status,
00748 List *headers, Octstr *body)
00749 {
00750 if (status == HTTP_OK || status == HTTP_ACCEPTED) {
00751 Dict *param;
00752 Octstr *msgid;
00753
00754 if ((param = clickatell_parse_body(body)) != NULL &&
00755 (msgid = dict_get(param, octstr_imm("ID"))) != NULL &&
00756 msgid != NULL) {
00757
00758
00759 if (DLR_IS_ENABLED_DEVICE(msg->sms.dlr_mask))
00760 dlr_add(conn->id, msgid, msg);
00761
00762 bb_smscconn_sent(conn, msg, NULL);
00763
00764 } else {
00765 error(0, "HTTP[%s]: Message was malformed or error was returned. SMSC response `%s'.",
00766 octstr_get_cstr(conn->id), octstr_get_cstr(body));
00767 bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_MALFORMED, octstr_duplicate(body));
00768 }
00769 dict_destroy(param);
00770
00771 } else {
00772 error(0, "HTTP[%s]: Message was rejected. SMSC reponse `%s'.",
00773 octstr_get_cstr(conn->id), octstr_get_cstr(body));
00774 bb_smscconn_send_failed(conn, msg,
00775 SMSCCONN_FAILED_REJECTED, octstr_duplicate(body));
00776 }
00777 }
00778
00779
00780 static void clickatell_receive_sms(SMSCConn *conn, HTTPClient *client,
00781 List *headers, Octstr *body, List *cgivars)
00782 {
00783 List *reply_headers;
00784 int ret;
00785 Octstr *apimsgid, *status, *timestamp, *retmsg, *dest, *charge;
00786 Octstr *api_id, *from, *to, *text, *charset, *udh;
00787 int httpstatus = HTTP_UNAUTHORIZED, dlrstat;
00788 Msg *dlrmsg, *momsg;
00789 struct tm tm;
00790
00791
00792 apimsgid = http_cgi_variable(cgivars, "apiMsgId");
00793 status = http_cgi_variable(cgivars, "status");
00794
00795 timestamp = http_cgi_variable(cgivars, "timestamp");
00796 dest = http_cgi_variable(cgivars, "to");
00797 charge = http_cgi_variable(cgivars, "charge");
00798
00799 api_id = http_cgi_variable(cgivars, "api_id");
00800 from = http_cgi_variable(cgivars, "from");
00801 to = http_cgi_variable(cgivars, "to");
00802 text = http_cgi_variable(cgivars, "text");
00803 charset = http_cgi_variable(cgivars, "charset");
00804 udh = http_cgi_variable(cgivars, "udh");
00805
00806 debug("smsc.http.clickatell", 0, "HTTP[%s]: Received a request",
00807 octstr_get_cstr(conn->id));
00808
00809 if (api_id != NULL && from != NULL && to != NULL && timestamp != NULL && text != NULL && charset != NULL && udh != NULL) {
00810
00811 debug("smsc.http.clickatell", 0, "HTTP[%s]: Received MO message from %s: <%s>",
00812 octstr_get_cstr(conn->id), octstr_get_cstr(from), octstr_get_cstr(text));
00813 momsg = msg_create(sms);
00814 momsg->sms.sms_type = mo;
00815 momsg->sms.sender = octstr_duplicate(from);
00816 momsg->sms.receiver = octstr_duplicate(to);
00817 momsg->sms.msgdata = octstr_duplicate(text);
00818 momsg->sms.charset = octstr_duplicate(charset);
00819 momsg->sms.service = octstr_duplicate(api_id);
00820 momsg->sms.binfo = octstr_duplicate(api_id);
00821 momsg->sms.smsc_id = octstr_duplicate(conn->id);
00822 if (octstr_len(udh) > 0) {
00823 momsg->sms.udhdata = octstr_duplicate(udh);
00824 }
00825 strptime(octstr_get_cstr(timestamp), "%Y-%m-%d %H:%M:%S", &tm);
00826 momsg->sms.time = gw_mktime(&tm);
00827
00828
00829 ret = bb_smscconn_receive(conn, momsg);
00830 httpstatus = HTTP_OK;
00831 retmsg = octstr_create("Thanks");
00832 } else if (apimsgid == NULL || status == NULL || timestamp == NULL || dest == NULL) {
00833 error(0, "HTTP[%s]: Insufficient args.",
00834 octstr_get_cstr(conn->id));
00835 httpstatus = HTTP_BAD_REQUEST;
00836 retmsg = octstr_create("Insufficient arguments, rejected.");
00837 } else {
00838 switch (atoi(octstr_get_cstr(status))) {
00839 case 1:
00840 case 5:
00841 case 6:
00842 case 7:
00843 case 9:
00844 case 10:
00845 dlrstat = 2;
00846 break;
00847 case 2:
00848 case 3:
00849 case 11:
00850 dlrstat = 4;
00851 break;
00852 case 4:
00853 case 8:
00854 dlrstat = 1;
00855 break;
00856 default:
00857 dlrstat = 16;
00858 break;
00859 }
00860 dlrmsg = dlr_find(conn->id,
00861 apimsgid,
00862 dest ,
00863 dlrstat);
00864
00865 if (dlrmsg != NULL) {
00866
00867 dlrmsg->sms.sms_type = report_mo;
00868 dlrmsg->sms.time = atoi(octstr_get_cstr(timestamp));
00869 if (charge) {
00870
00871
00872 dlrmsg->sms.binfo = octstr_duplicate(charge);
00873 }
00874
00875 ret = bb_smscconn_receive(conn, dlrmsg);
00876 httpstatus = (ret == 0 ? HTTP_OK : HTTP_FORBIDDEN);
00877 retmsg = octstr_create("Sent");
00878 } else {
00879 error(0,"HTTP[%s]: got DLR but could not find message or was not interested "
00880 "in it id<%s> dst<%s>, type<%d>",
00881 octstr_get_cstr(conn->id), octstr_get_cstr(apimsgid),
00882 octstr_get_cstr(dest), dlrstat);
00883 httpstatus = HTTP_OK;
00884 retmsg = octstr_create("Thanks");
00885 }
00886 }
00887
00888 reply_headers = gwlist_create();
00889 http_header_add(reply_headers, "Content-Type", "text/plain");
00890 debug("smsc.http.clickatell", 0, "HTTP[%s]: Sending reply `%s'.",
00891 octstr_get_cstr(conn->id), octstr_get_cstr(retmsg));
00892 http_send_reply(client, httpstatus, reply_headers, retmsg);
00893
00894 octstr_destroy(retmsg);
00895 http_destroy_headers(reply_headers);
00896 }
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910 static void brunet_send_sms(SMSCConn *conn, Msg *sms)
00911 {
00912 ConnData *conndata = conn->data;
00913 Octstr *url, *tid, *xser;
00914 List *headers;
00915 char id[UUID_STR_LEN + 1];
00916 int dcs;
00917
00918
00919
00920
00921
00922
00923 uuid_unparse(sms->sms.id, id);
00924 tid = octstr_create(id);
00925 octstr_replace(tid, octstr_imm("-"), octstr_imm(""));
00926
00927
00928 url = octstr_format("%S?MsIsdn=%E&Originator=%E",
00929 conndata->send_url, sms->sms.receiver, sms->sms.sender);
00930
00931
00932
00933
00934
00935
00936 if (octstr_len(sms->sms.binfo)) {
00937 octstr_url_decode(sms->sms.binfo);
00938 octstr_format_append(url, "&%S", sms->sms.binfo);
00939 }
00940
00941 if (octstr_search(url, octstr_create("CustomerId="), 0) == -1) {
00942 octstr_format_append(url, "&CustomerId=%S", conndata->username);
00943 }
00944
00945 if (octstr_search(url, octstr_create("TransactionId="), 0) == -1) {
00946 octstr_format_append(url, "&TransactionId=%S", tid);
00947 }
00948
00949 if (octstr_search(url, octstr_create("SMSCount="), 0) == -1) {
00950 octstr_format_append(url, "&%s", "SMSCount=1");
00951 }
00952
00953 if (octstr_search(url, octstr_create("ActionType="), 0) == -1) {
00954 octstr_format_append(url, "&%s", "ActionType=A");
00955 }
00956
00957 if (octstr_search(url, octstr_create("ServiceDeliveryType="), 0) == -1) {
00958 octstr_format_append(url, "&%s", "ServiceDeliveryType=P");
00959 }
00960
00961
00962
00963 if (sms->sms.coding == DC_UNDEF)
00964 sms->sms.coding = octstr_len(sms->sms.udhdata) > 0 ? DC_8BIT : DC_7BIT;
00965
00966 if (sms->sms.coding == DC_8BIT)
00967 octstr_format_append(url, "&MessageType=B&Text=%H", sms->sms.msgdata);
00968 else
00969 octstr_format_append(url, "&MessageType=S&Text=%E", sms->sms.msgdata);
00970
00971 dcs = fields_to_dcs(sms,
00972 (sms->sms.alt_dcs != SMS_PARAM_UNDEFINED ? sms->sms.alt_dcs : 0));
00973
00974
00975 xser = octstr_create("");
00976
00977 if (dcs != 0 && dcs != 4)
00978 octstr_format_append(xser, "0201%02x", dcs & 0xff);
00979
00980 if (octstr_len(sms->sms.udhdata)) {
00981 octstr_format_append(xser, "01%02x%H", octstr_len(sms->sms.udhdata),
00982 sms->sms.udhdata);
00983 }
00984 if (octstr_len(xser) > 0)
00985 octstr_format_append(url, "&XSer=%S", xser);
00986 octstr_destroy(xser);
00987
00988
00989 headers = http_create_empty_headers();
00990 debug("smsc.http.brunet", 0, "HTTP[%s]: Sending request <%s>",
00991 octstr_get_cstr(conn->id), octstr_get_cstr(url));
00992
00993
00994
00995
00996
00997 http_start_request(conndata->http_ref, HTTP_METHOD_GET, url, headers,
00998 NULL, 0, sms, NULL);
00999
01000 octstr_destroy(url);
01001 octstr_destroy(tid);
01002 http_destroy_headers(headers);
01003 }
01004
01005
01006
01007
01008
01009
01010
01011 static Dict *brunet_parse_body(Octstr *body)
01012 {
01013 Dict *param = NULL;
01014 List *words = NULL;
01015 long len;
01016 Octstr *word;
01017
01018 words = octstr_split_words(body);
01019 if ((len = gwlist_len(words)) > 0) {
01020 param = dict_create(4, (void(*)(void *)) octstr_destroy);
01021 while ((word = gwlist_extract_first(words)) != NULL) {
01022 List *l = octstr_split(word, octstr_imm("="));
01023 Octstr *key = gwlist_extract_first(l);
01024 Octstr *value = gwlist_extract_first(l);
01025 if (octstr_len(key))
01026 dict_put(param, key, value);
01027 octstr_destroy(key);
01028 octstr_destroy(word);
01029 gwlist_destroy(l, (void(*)(void *)) octstr_destroy);
01030 }
01031 }
01032 gwlist_destroy(words, (void(*)(void *)) octstr_destroy);
01033
01034 return param;
01035 }
01036
01037
01038 static void brunet_parse_reply(SMSCConn *conn, Msg *msg, int status,
01039 List *headers, Octstr *body)
01040 {
01041 if (status == HTTP_OK || status == HTTP_ACCEPTED) {
01042 Dict *param;
01043 Octstr *status;
01044
01045 if ((param = brunet_parse_body(body)) != NULL &&
01046 (status = dict_get(param, octstr_imm("Status"))) != NULL &&
01047 octstr_case_compare(status, octstr_imm("0")) == 0) {
01048 Octstr *msg_id;
01049
01050
01051 if ((msg_id = dict_get(param, octstr_imm("MessageId"))) != NULL)
01052 msg->sms.binfo = octstr_duplicate(msg_id);
01053
01054 bb_smscconn_sent(conn, msg, NULL);
01055
01056 } else {
01057 error(0, "HTTP[%s]: Message was malformed. SMSC response `%s'.",
01058 octstr_get_cstr(conn->id), octstr_get_cstr(body));
01059 bb_smscconn_send_failed(conn, msg,
01060 SMSCCONN_FAILED_MALFORMED, octstr_duplicate(body));
01061 }
01062 dict_destroy(param);
01063
01064 } else {
01065 error(0, "HTTP[%s]: Message was rejected. SMSC reponse `%s'.",
01066 octstr_get_cstr(conn->id), octstr_get_cstr(body));
01067 bb_smscconn_send_failed(conn, msg,
01068 SMSCCONN_FAILED_REJECTED, octstr_duplicate(body));
01069 }
01070 }
01071
01072
01073 static void brunet_receive_sms(SMSCConn *conn, HTTPClient *client,
01074 List *headers, Octstr *body, List *cgivars)
01075 {
01076 ConnData *conndata = conn->data;
01077 Octstr *user, *from, *to, *text, *udh, *date, *type;
01078 Octstr *retmsg;
01079 int mclass, mwi, coding, validity, deferred;
01080 List *reply_headers;
01081 int ret;
01082
01083 mclass = mwi = coding = validity = deferred = 0;
01084
01085 user = http_cgi_variable(cgivars, "CustomerId");
01086 from = http_cgi_variable(cgivars, "MsIsdn");
01087 to = http_cgi_variable(cgivars, "Recipient");
01088 text = http_cgi_variable(cgivars, "SMMO");
01089 udh = http_cgi_variable(cgivars, "XSer");
01090 date = http_cgi_variable(cgivars, "DateReceived");
01091 type = http_cgi_variable(cgivars, "MessageType");
01092
01093 debug("smsc.http.brunet", 0, "HTTP[%s]: Received a request",
01094 octstr_get_cstr(conn->id));
01095
01096 if (user == NULL || octstr_compare(user, conndata->username) != 0) {
01097 error(0, "HTTP[%s]: Authorization failure. CustomerId was <%s>.",
01098 octstr_get_cstr(conn->id), octstr_get_cstr(user));
01099 retmsg = octstr_create("Authorization failed for MO submission.");
01100 }
01101 else if (from == NULL || to == NULL || text == NULL) {
01102 error(0, "HTTP[%s]: Insufficient args.",
01103 octstr_get_cstr(conn->id));
01104 retmsg = octstr_create("Insufficient arguments, rejected.");
01105 }
01106 else {
01107 Msg *msg;
01108 msg = msg_create(sms);
01109
01110 debug("smsc.http.brunet", 0, "HTTP[%s]: Received new MO SMS.",
01111 octstr_get_cstr(conn->id));
01112
01113 msg->sms.sender = octstr_duplicate(from);
01114 msg->sms.receiver = octstr_duplicate(to);
01115 msg->sms.msgdata = octstr_duplicate(text);
01116 msg->sms.udhdata = octstr_duplicate(udh);
01117
01118 msg->sms.smsc_id = octstr_duplicate(conn->id);
01119 msg->sms.time = time(NULL);
01120 msg->sms.mclass = mclass;
01121 msg->sms.mwi = mwi;
01122 msg->sms.coding = coding;
01123 msg->sms.validity = validity;
01124 msg->sms.deferred = deferred;
01125
01126 ret = bb_smscconn_receive(conn, msg);
01127 if (ret == -1)
01128 retmsg = octstr_create("Status=1");
01129 else
01130 retmsg = octstr_create("Status=0");
01131 }
01132
01133 reply_headers = gwlist_create();
01134 http_header_add(reply_headers, "Content-Type", "text/plain");
01135 debug("smsc.http.brunet", 0, "HTTP[%s]: Sending reply `%s'.",
01136 octstr_get_cstr(conn->id), octstr_get_cstr(retmsg));
01137 http_send_reply(client, HTTP_OK, reply_headers, retmsg);
01138
01139 octstr_destroy(retmsg);
01140 http_destroy_headers(reply_headers);
01141 }
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153 static void xidris_send_sms(SMSCConn *conn, Msg *sms)
01154 {
01155 ConnData *conndata = conn->data;
01156 Octstr *url, *new_msg;
01157 List *headers;
01158 int dcs, esm_class;
01159
01160 url = new_msg = NULL;
01161 dcs = esm_class = 0;
01162
01163
01164 url = octstr_format("%S?"
01165 "app_id=%E&key=%E&dest_addr=%E&source_addr=%E",
01166 conndata->send_url, conndata->username,
01167 conndata->password, sms->sms.receiver, sms->sms.sender);
01168
01169 if (octstr_len(sms->sms.udhdata)) {
01170
01171
01172
01173 dcs = fields_to_dcs(sms, sms->sms.alt_dcs);
01174
01175
01176 esm_class = 0x03 | 0x40;
01177
01178
01179 new_msg = octstr_duplicate(sms->sms.udhdata);
01180 octstr_append(new_msg, sms->sms.msgdata);
01181
01182 octstr_format_append(url, "&type=200&dcs=%d&esm=%d&message=%H",
01183 dcs, esm_class, new_msg);
01184 } else {
01185
01186
01187 octstr_format_append(url, "&type=%E&message=%E",
01188 (sms->sms.mclass ? octstr_imm("1") : octstr_imm("0")),
01189 sms->sms.msgdata);
01190 }
01191
01192
01193
01194
01195
01196 if (octstr_len(sms->sms.account)) {
01197 octstr_url_decode(sms->sms.account);
01198 octstr_format_append(url, "&%s", octstr_get_cstr(sms->sms.account));
01199 }
01200
01201 headers = gwlist_create();
01202 debug("smsc.http.xidris", 0, "HTTP[%s]: Sending request <%s>",
01203 octstr_get_cstr(conn->id), octstr_get_cstr(url));
01204
01205 http_start_request(conndata->http_ref, HTTP_METHOD_GET, url, headers,
01206 NULL, 0, sms, NULL);
01207
01208 octstr_destroy(url);
01209 octstr_destroy(new_msg);
01210 http_destroy_headers(headers);
01211 }
01212
01213
01214
01215
01216
01217 static Octstr *parse_xml_tag(Octstr *body, Octstr *tag)
01218 {
01219 Octstr *stag, *etag, *ret;
01220 int spos, epos;
01221
01222 stag = octstr_format("<%s>", octstr_get_cstr(tag));
01223 if ((spos = octstr_search(body, stag, 0)) == -1) {
01224 octstr_destroy(stag);
01225 return NULL;
01226 }
01227 etag = octstr_format("</%s>", octstr_get_cstr(tag));
01228 if ((epos = octstr_search(body, etag, spos+octstr_len(stag))) == -1) {
01229 octstr_destroy(stag);
01230 octstr_destroy(etag);
01231 return NULL;
01232 }
01233
01234 ret = octstr_copy(body, spos+octstr_len(stag), epos+1 - (spos+octstr_len(etag)));
01235 octstr_strip_blanks(ret);
01236 octstr_strip_crlfs(ret);
01237
01238 octstr_destroy(stag);
01239 octstr_destroy(etag);
01240
01241 return ret;
01242 }
01243
01244 static void xidris_parse_reply(SMSCConn *conn, Msg *msg, int status,
01245 List *headers, Octstr *body)
01246 {
01247 Octstr *code, *desc, *mid;
01248
01249 if (status == HTTP_OK || status == HTTP_ACCEPTED) {
01250
01251 code = parse_xml_tag(body, octstr_imm("status"));
01252 desc = parse_xml_tag(body, octstr_imm("description"));
01253
01254
01255
01256
01257 mid = parse_xml_tag(body, octstr_imm("message_id"));
01258
01259 if (octstr_case_compare(code, octstr_imm("0")) == 0 && mid != NULL) {
01260
01261 msg->sms.binfo = octstr_duplicate(mid);
01262
01263
01264 if (DLR_IS_ENABLED_DEVICE(msg->sms.dlr_mask))
01265 dlr_add(conn->id, mid, msg);
01266
01267 octstr_destroy(mid);
01268 bb_smscconn_sent(conn, msg, NULL);
01269
01270 } else {
01271 error(0, "HTTP[%s]: Message not accepted. Status code <%s> "
01272 "description `%s'.", octstr_get_cstr(conn->id),
01273 octstr_get_cstr(code), octstr_get_cstr(desc));
01274 bb_smscconn_send_failed(conn, msg,
01275 SMSCCONN_FAILED_MALFORMED, octstr_duplicate(desc));
01276 }
01277 } else {
01278 error(0, "HTTP[%s]: Message was rejected. SMSC reponse was:",
01279 octstr_get_cstr(conn->id));
01280 octstr_dump(body, 0);
01281 bb_smscconn_send_failed(conn, msg,
01282 SMSCCONN_FAILED_REJECTED, octstr_create("REJECTED"));
01283 }
01284 }
01285
01286
01287 static void xidris_receive_sms(SMSCConn *conn, HTTPClient *client,
01288 List *headers, Octstr *body, List *cgivars)
01289 {
01290 ConnData *conndata = conn->data;
01291 Octstr *user, *pass, *from, *to, *text, *account, *binfo;
01292 Octstr *state, *mid, *dest;
01293 Octstr *retmsg;
01294 int mclass, mwi, coding, validity, deferred;
01295 List *reply_headers;
01296 int ret, status;
01297
01298 mclass = mwi = coding = validity = deferred = 0;
01299 retmsg = NULL;
01300
01301
01302 user = http_cgi_variable(cgivars, "app_id");
01303 pass = http_cgi_variable(cgivars, "key");
01304
01305
01306 from = http_cgi_variable(cgivars, "source_addr");
01307 to = http_cgi_variable(cgivars, "dest_addr");
01308 text = http_cgi_variable(cgivars, "message");
01309 account = http_cgi_variable(cgivars, "operator");
01310 binfo = http_cgi_variable(cgivars, "tariff");
01311
01312
01313 state = http_cgi_variable(cgivars, "state");
01314 mid = http_cgi_variable(cgivars, "message_id");
01315 dest = http_cgi_variable(cgivars, "dest_addr");
01316
01317 debug("smsc.http.xidris", 0, "HTTP[%s]: Received a request",
01318 octstr_get_cstr(conn->id));
01319
01320 if (user == NULL || pass == NULL ||
01321 octstr_compare(user, conndata->username) != 0 ||
01322 octstr_compare(pass, conndata->password) != 0) {
01323 error(0, "HTTP[%s]: Authorization failure. username was <%s>.",
01324 octstr_get_cstr(conn->id), octstr_get_cstr(user));
01325 retmsg = octstr_create("Authorization failed for MO submission.");
01326 status = HTTP_UNAUTHORIZED;
01327 }
01328 else if (state != NULL && mid != NULL && dest != NULL) {
01329 Msg *dlrmsg;
01330 int dlrstat = -1;
01331
01332 if (octstr_compare(state, octstr_imm("DELIVRD")) == 0)
01333 dlrstat = DLR_SUCCESS;
01334 else if (octstr_compare(state, octstr_imm("ACCEPTD")) == 0)
01335 dlrstat = DLR_BUFFERED;
01336 else
01337 dlrstat = DLR_FAIL;
01338
01339 dlrmsg = dlr_find(conn->id,
01340 mid,
01341 dest ,
01342 dlrstat);
01343
01344 if (dlrmsg != NULL) {
01345 dlrmsg->sms.msgdata = octstr_duplicate(mid);
01346 dlrmsg->sms.sms_type = report_mo;
01347
01348 ret = bb_smscconn_receive(conn, dlrmsg);
01349 status = (ret == 0 ? HTTP_OK : HTTP_FORBIDDEN);
01350 } else {
01351 error(0,"HTTP[%s]: got DLR but could not find message or was not interested "
01352 "in it id<%s> dst<%s>, type<%d>",
01353 octstr_get_cstr(conn->id), octstr_get_cstr(mid),
01354 octstr_get_cstr(dest), dlrstat);
01355 status = HTTP_OK;
01356 }
01357
01358 }
01359 else if (from == NULL || to == NULL || text == NULL) {
01360 error(0, "HTTP[%s]: Insufficient args.",
01361 octstr_get_cstr(conn->id));
01362 retmsg = octstr_create("Insufficient arguments, rejected.");
01363 status = HTTP_BAD_REQUEST;
01364 }
01365 else {
01366 Msg *msg;
01367 msg = msg_create(sms);
01368
01369 debug("smsc.http.xidris", 0, "HTTP[%s]: Received new MO SMS.",
01370 octstr_get_cstr(conn->id));
01371
01372 msg->sms.sender = octstr_duplicate(from);
01373 msg->sms.receiver = octstr_duplicate(to);
01374 msg->sms.msgdata = octstr_duplicate(text);
01375 msg->sms.account = octstr_duplicate(account);
01376 msg->sms.binfo = octstr_duplicate(binfo);
01377
01378 msg->sms.smsc_id = octstr_duplicate(conn->id);
01379 msg->sms.time = time(NULL);
01380 msg->sms.mclass = mclass;
01381 msg->sms.mwi = mwi;
01382 msg->sms.coding = coding;
01383 msg->sms.validity = validity;
01384 msg->sms.deferred = deferred;
01385
01386 ret = bb_smscconn_receive(conn, msg);
01387 status = (ret == 0 ? HTTP_OK : HTTP_FORBIDDEN);
01388 }
01389
01390 reply_headers = gwlist_create();
01391 debug("smsc.http.xidris", 0, "HTTP[%s]: Sending reply with HTTP status <%d>.",
01392 octstr_get_cstr(conn->id), status);
01393
01394 http_send_reply(client, status, reply_headers, retmsg);
01395
01396 octstr_destroy(retmsg);
01397 http_destroy_headers(reply_headers);
01398 }
01399
01400
01401
01402
01403
01404
01405
01406
01407 static void wapme_smsproxy_send_sms(SMSCConn *conn, Msg *sms)
01408 {
01409 ConnData *conndata = conn->data;
01410 Octstr *url;
01411 List *headers;
01412
01413 url = octstr_format("%S?command=forward&smsText=%E&phoneNumber=%E"
01414 "&serviceNumber=%E&smsc=%E",
01415 conndata->send_url,
01416 sms->sms.msgdata, sms->sms.sender, sms->sms.receiver,
01417 sms->sms.smsc_id);
01418
01419 headers = gwlist_create();
01420 debug("smsc.http.wapme", 0, "HTTP[%s]: Start request",
01421 octstr_get_cstr(conn->id));
01422 http_start_request(conndata->http_ref, HTTP_METHOD_GET, url, headers,
01423 NULL, 0, sms, NULL);
01424
01425 octstr_destroy(url);
01426 http_destroy_headers(headers);
01427 }
01428
01429 static void wapme_smsproxy_parse_reply(SMSCConn *conn, Msg *msg, int status,
01430 List *headers, Octstr *body)
01431 {
01432 if (status == HTTP_OK || status == HTTP_ACCEPTED) {
01433 bb_smscconn_sent(conn, msg, NULL);
01434 } else {
01435 bb_smscconn_send_failed(conn, msg,
01436 SMSCCONN_FAILED_MALFORMED, octstr_duplicate(body));
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
01478
01479
01480
01481
01482 static void generic_send_sms(SMSCConn *conn, Msg *sms)
01483 {
01484 ConnData *conndata = conn->data;
01485 Octstr *url;
01486 List *headers;
01487
01488
01489
01490
01491 url = urltrans_fill_escape_codes(conndata->send_url, sms);
01492
01493 headers = gwlist_create();
01494 debug("smsc.http.generic", 0, "HTTP[%s]: Sending request <%s>",
01495 octstr_get_cstr(conn->id), octstr_get_cstr(url));
01496 http_start_request(conndata->http_ref, HTTP_METHOD_GET, url, headers,
01497 NULL, 0, sms, NULL);
01498
01499 octstr_destroy(url);
01500 http_destroy_headers(headers);
01501 }
01502
01503 static void generic_parse_reply(SMSCConn *conn, Msg *msg, int status,
01504 List *headers, Octstr *body)
01505 {
01506 ConnData *conndata = conn->data;
01507 size_t n_match = 1;
01508 regmatch_t p_match[10];
01509
01510
01511
01512
01513
01514
01515 if ((conndata->success_regex != NULL) &&
01516 (gw_regex_exec(conndata->success_regex, body, n_match, p_match, 0) == 0)) {
01517 bb_smscconn_sent(conn, msg, NULL);
01518 }
01519 else if ((conndata->permfail_regex != NULL) &&
01520 (gw_regex_exec(conndata->permfail_regex, body, n_match, p_match, 0) == 0)) {
01521 error(0, "HTTP[%s]: Message not accepted.", octstr_get_cstr(conn->id));
01522 bb_smscconn_send_failed(conn, msg,
01523 SMSCCONN_FAILED_MALFORMED, octstr_duplicate(body));
01524 }
01525 else if ((conndata->tempfail_regex != NULL) &&
01526 (gw_regex_exec(conndata->tempfail_regex, body, n_match, p_match, 0) == 0)) {
01527 warning(0, "HTTP[%s]: Message temporary not accepted, will retry.",
01528 octstr_get_cstr(conn->id));
01529 bb_smscconn_send_failed(conn, msg,
01530 SMSCCONN_FAILED_TEMPORARILY, octstr_duplicate(body));
01531 }
01532 else {
01533 error(0, "HTTP[%s]: Message was rejected. SMSC reponse was:",
01534 octstr_get_cstr(conn->id));
01535 octstr_dump(body, 0);
01536 bb_smscconn_send_failed(conn, msg,
01537 SMSCCONN_FAILED_REJECTED, octstr_create("REJECTED"));
01538 }
01539 }
01540
01541
01542
01543
01544
01545
01546 static int httpsmsc_send(SMSCConn *conn, Msg *msg)
01547 {
01548 ConnData *conndata = conn->data;
01549 Msg *sms = msg_duplicate(msg);
01550 double delay = 0;
01551
01552 if (conn->throughput > 0) {
01553 delay = 1.0 / conn->throughput;
01554 }
01555
01556
01557 if (conndata->alt_charset &&
01558 charset_convert(sms->sms.msgdata, DEFAULT_CHARSET,
01559 octstr_get_cstr(conndata->alt_charset)) != 0)
01560 error(0, "Failed to convert msgdata from charset <%s> to <%s>, will send as is.",
01561 DEFAULT_CHARSET, octstr_get_cstr(conndata->alt_charset));
01562
01563 conndata->open_sends++;
01564 conndata->send_sms(conn, sms);
01565
01566
01567 if (conn->throughput > 0)
01568 gwthread_sleep(delay);
01569
01570 return 0;
01571 }
01572
01573
01574 static long httpsmsc_queued(SMSCConn *conn)
01575 {
01576 ConnData *conndata = conn->data;
01577
01578 return (conndata ? (conn->status != SMSCCONN_DEAD ?
01579 conndata->open_sends : 0) : 0);
01580 }
01581
01582
01583 static int httpsmsc_shutdown(SMSCConn *conn, int finish_sending)
01584 {
01585 ConnData *conndata = conn->data;
01586
01587 debug("httpsmsc_shutdown", 0, "HTTP[%s]: Shutting down",
01588 octstr_get_cstr(conn->id));
01589 conn->why_killed = SMSCCONN_KILLED_SHUTDOWN;
01590 conndata->shutdown = 1;
01591
01592 http_close_port(conndata->port);
01593 return 0;
01594 }
01595
01596
01597 int smsc_http_create(SMSCConn *conn, CfgGroup *cfg)
01598 {
01599 ConnData *conndata = NULL;
01600 Octstr *type;
01601 long portno;
01602 int ssl = 0;
01603 Octstr *os;
01604
01605 if (cfg_get_integer(&portno, cfg, octstr_imm("port")) == -1) {
01606 error(0, "HTTP[%s]: 'port' invalid in smsc 'http' record.",
01607 octstr_get_cstr(conn->id));
01608 return -1;
01609 }
01610 cfg_get_bool(&ssl, cfg, octstr_imm("use-ssl"));
01611 if ((type = cfg_get(cfg, octstr_imm("system-type")))==NULL) {
01612 error(0, "HTTP[%s]: 'type' missing in smsc 'http' record.",
01613 octstr_get_cstr(conn->id));
01614 octstr_destroy(type);
01615 return -1;
01616 }
01617 conndata = gw_malloc(sizeof(ConnData));
01618 conndata->http_ref = NULL;
01619 conndata->success_regex =
01620 conndata->permfail_regex = conndata->tempfail_regex = NULL;
01621
01622 conndata->allow_ip = cfg_get(cfg, octstr_imm("connect-allow-ip"));
01623 conndata->send_url = cfg_get(cfg, octstr_imm("send-url"));
01624 conndata->dlr_url = cfg_get(cfg, octstr_imm("dlr-url"));
01625 conndata->username = cfg_get(cfg, octstr_imm("smsc-username"));
01626 conndata->password = cfg_get(cfg, octstr_imm("smsc-password"));
01627 conndata->system_id = cfg_get(cfg, octstr_imm("system-id"));
01628 cfg_get_bool(&conndata->no_sender, cfg, octstr_imm("no-sender"));
01629 cfg_get_bool(&conndata->no_coding, cfg, octstr_imm("no-coding"));
01630 cfg_get_bool(&conndata->no_sep, cfg, octstr_imm("no-sep"));
01631 conndata->proxy = cfg_get(cfg, octstr_imm("system-id"));
01632 conndata->alt_charset = cfg_get(cfg, octstr_imm("alt-charset"));
01633
01634 if (conndata->send_url == NULL)
01635 panic(0, "HTTP[%s]: Sending not allowed. No 'send-url' specified.",
01636 octstr_get_cstr(conn->id));
01637
01638 if (octstr_case_compare(type, octstr_imm("kannel")) == 0) {
01639 if (conndata->username == NULL || conndata->password == NULL) {
01640 error(0, "HTTP[%s]: 'username' and 'password' required for Kannel http smsc",
01641 octstr_get_cstr(conn->id));
01642 goto error;
01643 }
01644 conndata->receive_sms = kannel_receive_sms;
01645 conndata->send_sms = kannel_send_sms;
01646 conndata->parse_reply = kannel_parse_reply;
01647 }
01648 else if (octstr_case_compare(type, octstr_imm("brunet")) == 0) {
01649 if (conndata->username == NULL) {
01650 error(0, "HTTP[%s]: 'username' (=CustomerId) required for bruNET http smsc",
01651 octstr_get_cstr(conn->id));
01652 goto error;
01653 }
01654 conndata->receive_sms = brunet_receive_sms;
01655 conndata->send_sms = brunet_send_sms;
01656 conndata->parse_reply = brunet_parse_reply;
01657 }
01658 else if (octstr_case_compare(type, octstr_imm("xidris")) == 0) {
01659 if (conndata->username == NULL || conndata->password == NULL) {
01660 error(0, "HTTP[%s]: 'username' and 'password' required for Xidris http smsc",
01661 octstr_get_cstr(conn->id));
01662 goto error;
01663 }
01664 conndata->receive_sms = xidris_receive_sms;
01665 conndata->send_sms = xidris_send_sms;
01666 conndata->parse_reply = xidris_parse_reply;
01667 }
01668 else if (octstr_case_compare(type, octstr_imm("wapme")) == 0) {
01669 if (conndata->username == NULL || conndata->password == NULL) {
01670 error(0, "HTTP[%s]: 'username' and 'password' required for Wapme http smsc",
01671 octstr_get_cstr(conn->id));
01672 goto error;
01673 }
01674 conndata->receive_sms = kannel_receive_sms;
01675 conndata->send_sms = wapme_smsproxy_send_sms;
01676 conndata->parse_reply = wapme_smsproxy_parse_reply;
01677 }
01678 else if (octstr_case_compare(type, octstr_imm("clickatell")) == 0) {
01679
01680 conndata->receive_sms = clickatell_receive_sms;
01681 conndata->send_sms = clickatell_send_sms;
01682 conndata->parse_reply = clickatell_parse_reply;
01683 }
01684 else if (octstr_case_compare(type, octstr_imm("generic")) == 0) {
01685
01686 if ((os = cfg_get(cfg, octstr_imm("status-success-regex"))) == NULL) {
01687 error(0, "HTTP[%s]: 'status-success-regex' required for generic http smsc",
01688 octstr_get_cstr(conn->id));
01689 goto error;
01690 }
01691 conndata->receive_sms = kannel_receive_sms;
01692 conndata->send_sms = generic_send_sms;
01693 conndata->parse_reply = generic_parse_reply;
01694
01695
01696 if (os != NULL) {
01697 if ((conndata->success_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
01698 panic(0, "Could not compile regex pattern '%s'", octstr_get_cstr(os));
01699 octstr_destroy(os);
01700 }
01701 if ((os = cfg_get(cfg, octstr_imm("status-permfail-regex"))) != NULL) {
01702 if ((conndata->permfail_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
01703 panic(0, "Could not compile regex pattern '%s'", octstr_get_cstr(os));
01704 octstr_destroy(os);
01705 }
01706 if ((os = cfg_get(cfg, octstr_imm("status-tempfail-regex"))) != NULL) {
01707 if ((conndata->tempfail_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
01708 panic(0, "Could not compile regex pattern '%s'", octstr_get_cstr(os));
01709 octstr_destroy(os);
01710 }
01711 }
01712
01713
01714
01715 else {
01716 error(0, "HTTP[%s]: system-type '%s' unknown smsc 'http' record.",
01717 octstr_get_cstr(conn->id), octstr_get_cstr(type));
01718
01719 goto error;
01720 }
01721 conndata->open_sends = 0;
01722 conndata->http_ref = http_caller_create();
01723
01724 conn->data = conndata;
01725 conn->name = octstr_format("HTTP:%S", type);
01726 conn->status = SMSCCONN_ACTIVE;
01727 conn->connect_time = time(NULL);
01728
01729 conn->shutdown = httpsmsc_shutdown;
01730 conn->queued = httpsmsc_queued;
01731 conn->send_msg = httpsmsc_send;
01732
01733 if (http_open_port_if(portno, ssl, conn->our_host)==-1)
01734 goto error;
01735
01736 conndata->port = portno;
01737 conndata->shutdown = 0;
01738
01739 if ((conndata->receive_thread =
01740 gwthread_create(httpsmsc_receiver, conn)) == -1)
01741 goto error;
01742
01743 if ((conndata->send_cb_thread =
01744 gwthread_create(httpsmsc_send_cb, conn)) == -1)
01745 goto error;
01746
01747 info(0, "HTTP[%s]: Initiated and ready", octstr_get_cstr(conn->id));
01748
01749 octstr_destroy(type);
01750 return 0;
01751
01752 error:
01753 error(0, "HTTP[%s]: Failed to create http smsc connection",
01754 octstr_get_cstr(conn->id));
01755
01756 conn->data = NULL;
01757 conndata_destroy(conndata);
01758 conn->why_killed = SMSCCONN_KILLED_CANNOT_CONNECT;
01759 conn->status = SMSCCONN_DEAD;
01760 octstr_destroy(type);
01761 return -1;
01762 }
01763
See file LICENSE for details about the license agreement for using,
modifying, copying or deriving work from this software.