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 #include <signal.h>
00066 #include <time.h>
00067
00068 #include "gwlib/gwlib.h"
00069 #include "gwlib/regex.h"
00070 #include "smscconn.h"
00071 #include "smscconn_p.h"
00072 #include "bb_smscconn_cb.h"
00073 #include "sms.h"
00074
00075 extern Counter *split_msg_counter;
00076
00077
00078
00079
00080 #define SMSCCONN_RECONNECT_DELAY 10.0
00081
00082
00083
00084
00085
00086
00087 static void init_reroute(SMSCConn *conn, CfgGroup *grp)
00088 {
00089 Octstr *rule;
00090 long i;
00091
00092 if (cfg_get_bool(&conn->reroute_dlr, grp, octstr_imm("reroute-dlr")) == -1)
00093 conn->reroute_dlr = 0;
00094 info(0, "DLR rerouting for smsc id <%s> %s.", octstr_get_cstr(conn->id), (conn->reroute_dlr?"enabled":"disabled"));
00095
00096 if (cfg_get_bool(&conn->reroute, grp, octstr_imm("reroute")) != -1) {
00097 debug("smscconn",0,"Adding general internal routing for smsc id <%s>",
00098 octstr_get_cstr(conn->id));
00099 return;
00100 }
00101
00102 if ((conn->reroute_to_smsc = cfg_get(grp, octstr_imm("reroute-smsc-id"))) != NULL) {
00103
00104 debug("smscconn",0,"Adding internal routing: smsc id <%s> to smsc id <%s>",
00105 octstr_get_cstr(conn->id), octstr_get_cstr(conn->reroute_to_smsc));
00106 return;
00107 }
00108
00109 if ((rule = cfg_get(grp, octstr_imm("reroute-receiver"))) != NULL) {
00110 List *routes;
00111
00112
00113 conn->reroute_by_receiver = dict_create(100, (void(*)(void *)) octstr_destroy);
00114
00115 routes = octstr_split(rule, octstr_imm(";"));
00116 for (i = 0; i < gwlist_len(routes); i++) {
00117 Octstr *item = gwlist_get(routes, i);
00118 Octstr *smsc, *receiver;
00119 List *receivers;
00120
00121
00122 receivers = octstr_split(item, octstr_imm(","));
00123 smsc = gwlist_extract_first(receivers);
00124 if (smsc)
00125 octstr_strip_blanks(smsc);
00126
00127 while((receiver = gwlist_extract_first(receivers))) {
00128 octstr_strip_blanks(receiver);
00129 debug("smscconn",0,"Adding internal routing for smsc id <%s>: "
00130 "receiver <%s> to smsc id <%s>",
00131 octstr_get_cstr(conn->id), octstr_get_cstr(receiver),
00132 octstr_get_cstr(smsc));
00133 if (!dict_put_once(conn->reroute_by_receiver, receiver, octstr_duplicate(smsc)))
00134 panic(0, "Could not set internal routing for smsc id <%s>: "
00135 "receiver <%s> to smsc id <%s>, because receiver has already routing entry!",
00136 octstr_get_cstr(conn->id), octstr_get_cstr(receiver),
00137 octstr_get_cstr(smsc));
00138 octstr_destroy(receiver);
00139 }
00140 octstr_destroy(smsc);
00141 gwlist_destroy(receivers, octstr_destroy_item);
00142 }
00143 octstr_destroy(rule);
00144 gwlist_destroy(routes, octstr_destroy_item);
00145 }
00146 }
00147
00148
00149 SMSCConn *smscconn_create(CfgGroup *grp, int start_as_stopped)
00150 {
00151 SMSCConn *conn;
00152 Octstr *smsc_type;
00153 int ret;
00154 Octstr *allowed_smsc_id_regex;
00155 Octstr *denied_smsc_id_regex;
00156 Octstr *allowed_prefix_regex;
00157 Octstr *denied_prefix_regex;
00158 Octstr *preferred_prefix_regex;
00159 Octstr *tmp;
00160
00161 if (grp == NULL)
00162 return NULL;
00163
00164 conn = gw_malloc(sizeof(*conn));
00165 memset(conn, 0, sizeof(*conn));
00166
00167 conn->why_killed = SMSCCONN_ALIVE;
00168 conn->status = SMSCCONN_CONNECTING;
00169 conn->connect_time = -1;
00170 conn->is_stopped = start_as_stopped;
00171
00172 conn->received = counter_create();
00173 conn->sent = counter_create();
00174 conn->failed = counter_create();
00175 conn->flow_mutex = mutex_create();
00176
00177 #define GET_OPTIONAL_VAL(x, n) x = cfg_get(grp, octstr_imm(n))
00178 #define SPLIT_OPTIONAL_VAL(x, n) \
00179 do { \
00180 Octstr *tmp = cfg_get(grp, octstr_imm(n)); \
00181 if (tmp) x = octstr_split(tmp, octstr_imm(";")); \
00182 else x = NULL; \
00183 octstr_destroy(tmp); \
00184 }while(0)
00185
00186 GET_OPTIONAL_VAL(conn->id, "smsc-id");
00187 SPLIT_OPTIONAL_VAL(conn->allowed_smsc_id, "allowed-smsc-id");
00188 SPLIT_OPTIONAL_VAL(conn->denied_smsc_id, "denied-smsc-id");
00189 SPLIT_OPTIONAL_VAL(conn->preferred_smsc_id, "preferred-smsc-id");
00190 GET_OPTIONAL_VAL(conn->allowed_prefix, "allowed-prefix");
00191 GET_OPTIONAL_VAL(conn->denied_prefix, "denied-prefix");
00192 GET_OPTIONAL_VAL(conn->preferred_prefix, "preferred-prefix");
00193 GET_OPTIONAL_VAL(conn->unified_prefix, "unified-prefix");
00194 GET_OPTIONAL_VAL(conn->our_host, "our-host");
00195 GET_OPTIONAL_VAL(conn->log_file, "log-file");
00196 cfg_get_bool(&conn->alt_dcs, grp, octstr_imm("alt-dcs"));
00197
00198 GET_OPTIONAL_VAL(allowed_smsc_id_regex, "allowed-smsc-id-regex");
00199 if (allowed_smsc_id_regex != NULL)
00200 if ((conn->allowed_smsc_id_regex = gw_regex_comp(allowed_smsc_id_regex, REG_EXTENDED)) == NULL)
00201 panic(0, "Could not compile pattern '%s'", octstr_get_cstr(allowed_smsc_id_regex));
00202 GET_OPTIONAL_VAL(denied_smsc_id_regex, "denied-smsc-id-regex");
00203 if (denied_smsc_id_regex != NULL)
00204 if ((conn->denied_smsc_id_regex = gw_regex_comp(denied_smsc_id_regex, REG_EXTENDED)) == NULL)
00205 panic(0, "Could not compile pattern '%s'", octstr_get_cstr(denied_smsc_id_regex));
00206 GET_OPTIONAL_VAL(allowed_prefix_regex, "allowed-prefix-regex");
00207 if (allowed_prefix_regex != NULL)
00208 if ((conn->allowed_prefix_regex = gw_regex_comp(allowed_prefix_regex, REG_EXTENDED)) == NULL)
00209 panic(0, "Could not compile pattern '%s'", octstr_get_cstr(allowed_prefix_regex));
00210 GET_OPTIONAL_VAL(denied_prefix_regex, "denied-prefix-regex");
00211 if (denied_prefix_regex != NULL)
00212 if ((conn->denied_prefix_regex = gw_regex_comp(denied_prefix_regex, REG_EXTENDED)) == NULL)
00213 panic(0, "Could not compile pattern '%s'", octstr_get_cstr(denied_prefix_regex));
00214 GET_OPTIONAL_VAL(preferred_prefix_regex, "preferred-prefix-regex");
00215 if (preferred_prefix_regex != NULL)
00216 if ((conn->preferred_prefix_regex = gw_regex_comp(preferred_prefix_regex, REG_EXTENDED)) == NULL)
00217 panic(0, "Could not compile pattern '%s'", octstr_get_cstr(preferred_prefix_regex));
00218
00219 if ((tmp = cfg_get(grp, octstr_imm("throughput"))) != NULL) {
00220 if (octstr_parse_double(&conn->throughput, tmp, 0) == -1)
00221 conn->throughput = 0;
00222 octstr_destroy(tmp);
00223 info(0, "Set throughput to %.3f for smsc id <%s>", conn->throughput, octstr_get_cstr(conn->id));
00224 }
00225
00226
00227 init_reroute(conn, grp);
00228
00229 if (cfg_get_integer(&conn->log_level, grp, octstr_imm("log-level")) == -1)
00230 conn->log_level = 0;
00231
00232 if (cfg_get_integer(&conn->max_sms_octets, grp, octstr_imm("max-sms-octets")) == -1)
00233 conn->max_sms_octets = MAX_SMS_OCTETS;
00234
00235
00236 if (conn->log_file)
00237 conn->log_idx = log_open(octstr_get_cstr(conn->log_file),
00238 conn->log_level, GW_EXCL);
00239 #undef GET_OPTIONAL_VAL
00240 #undef SPLIT_OPTIONAL_VAL
00241
00242 if (conn->allowed_smsc_id && conn->denied_smsc_id)
00243 warning(0, "Both 'allowed-smsc-id' and 'denied-smsc-id' set, deny-list "
00244 "automatically ignored");
00245 if (conn->allowed_smsc_id_regex && conn->denied_smsc_id_regex)
00246 warning(0, "Both 'allowed-smsc-id_regex' and 'denied-smsc-id_regex' set, deny-regex "
00247 "automatically ignored");
00248
00249 if (cfg_get_integer(&conn->reconnect_delay, grp,
00250 octstr_imm("reconnect-delay")) == -1)
00251 conn->reconnect_delay = SMSCCONN_RECONNECT_DELAY;
00252
00253 smsc_type = cfg_get(grp, octstr_imm("smsc"));
00254 if (smsc_type == NULL) {
00255 error(0, "Required field 'smsc' missing for smsc group.");
00256 smscconn_destroy(conn);
00257 octstr_destroy(smsc_type);
00258 return NULL;
00259 }
00260
00261 if (octstr_compare(smsc_type, octstr_imm("fake")) == 0)
00262 ret = smsc_fake_create(conn, grp);
00263 else if (octstr_compare(smsc_type, octstr_imm("cimd2")) == 0)
00264 ret = smsc_cimd2_create(conn, grp);
00265 else if (octstr_compare(smsc_type, octstr_imm("emi")) == 0)
00266 ret = smsc_emi2_create(conn, grp);
00267 else if (octstr_compare(smsc_type, octstr_imm("http")) == 0)
00268 ret = smsc_http_create(conn, grp);
00269 else if (octstr_compare(smsc_type, octstr_imm("smpp")) == 0)
00270 ret = smsc_smpp_create(conn, grp);
00271 else if (octstr_compare(smsc_type, octstr_imm("at")) == 0)
00272 ret = smsc_at2_create(conn,grp);
00273 else if (octstr_compare(smsc_type, octstr_imm("cgw")) == 0)
00274 ret = smsc_cgw_create(conn,grp);
00275 else if (octstr_compare(smsc_type, octstr_imm("smasi")) == 0)
00276 ret = smsc_smasi_create(conn, grp);
00277 else if (octstr_compare(smsc_type, octstr_imm("oisd")) == 0)
00278 ret = smsc_oisd_create(conn, grp);
00279 else
00280 ret = smsc_wrapper_create(conn, grp);
00281
00282 octstr_destroy(smsc_type);
00283 if (ret == -1) {
00284 smscconn_destroy(conn);
00285 return NULL;
00286 }
00287 gw_assert(conn->send_msg != NULL);
00288
00289 bb_smscconn_ready(conn);
00290
00291 return conn;
00292 }
00293
00294
00295 void smscconn_shutdown(SMSCConn *conn, int finish_sending)
00296 {
00297 gw_assert(conn != NULL);
00298 mutex_lock(conn->flow_mutex);
00299 if (conn->status == SMSCCONN_DEAD) {
00300 mutex_unlock(conn->flow_mutex);
00301 return;
00302 }
00303
00304
00305 if (conn->shutdown) {
00306
00307
00308
00309
00310 mutex_unlock(conn->flow_mutex);
00311 conn->shutdown(conn, finish_sending);
00312 }
00313 else {
00314 conn->why_killed = SMSCCONN_KILLED_SHUTDOWN;
00315 mutex_unlock(conn->flow_mutex);
00316 }
00317
00318 return;
00319 }
00320
00321
00322 int smscconn_destroy(SMSCConn *conn)
00323 {
00324 if (conn == NULL)
00325 return 0;
00326 if (conn->status != SMSCCONN_DEAD)
00327 return -1;
00328 mutex_lock(conn->flow_mutex);
00329
00330 counter_destroy(conn->received);
00331 counter_destroy(conn->sent);
00332 counter_destroy(conn->failed);
00333
00334 octstr_destroy(conn->name);
00335 octstr_destroy(conn->id);
00336 gwlist_destroy(conn->allowed_smsc_id, octstr_destroy_item);
00337 gwlist_destroy(conn->denied_smsc_id, octstr_destroy_item);
00338 gwlist_destroy(conn->preferred_smsc_id, octstr_destroy_item);
00339 octstr_destroy(conn->denied_prefix);
00340 octstr_destroy(conn->allowed_prefix);
00341 octstr_destroy(conn->preferred_prefix);
00342 octstr_destroy(conn->unified_prefix);
00343 octstr_destroy(conn->our_host);
00344 octstr_destroy(conn->log_file);
00345
00346 if (conn->denied_smsc_id_regex != NULL) gw_regex_destroy(conn->denied_smsc_id_regex);
00347 if (conn->allowed_smsc_id_regex != NULL) gw_regex_destroy(conn->allowed_smsc_id_regex);
00348 if (conn->preferred_prefix_regex != NULL) gw_regex_destroy(conn->preferred_prefix_regex);
00349 if (conn->denied_prefix_regex != NULL) gw_regex_destroy(conn->denied_prefix_regex);
00350 if (conn->allowed_prefix_regex != NULL) gw_regex_destroy(conn->allowed_prefix_regex);
00351
00352 octstr_destroy(conn->reroute_to_smsc);
00353 dict_destroy(conn->reroute_by_receiver);
00354
00355 mutex_unlock(conn->flow_mutex);
00356 mutex_destroy(conn->flow_mutex);
00357
00358 gw_free(conn);
00359 return 0;
00360 }
00361
00362
00363 int smscconn_stop(SMSCConn *conn)
00364 {
00365 gw_assert(conn != NULL);
00366 mutex_lock(conn->flow_mutex);
00367 if (conn->status == SMSCCONN_DEAD || conn->is_stopped != 0
00368 || conn->why_killed != SMSCCONN_ALIVE)
00369 {
00370 mutex_unlock(conn->flow_mutex);
00371 return -1;
00372 }
00373 conn->is_stopped = 1;
00374 mutex_unlock(conn->flow_mutex);
00375
00376 if (conn->stop_conn)
00377 conn->stop_conn(conn);
00378
00379 return 0;
00380 }
00381
00382
00383 void smscconn_start(SMSCConn *conn)
00384 {
00385 gw_assert(conn != NULL);
00386 mutex_lock(conn->flow_mutex);
00387 if (conn->status == SMSCCONN_DEAD || conn->is_stopped == 0) {
00388 mutex_unlock(conn->flow_mutex);
00389 return;
00390 }
00391 conn->is_stopped = 0;
00392 mutex_unlock(conn->flow_mutex);
00393
00394 if (conn->start_conn)
00395 conn->start_conn(conn);
00396 }
00397
00398
00399 const Octstr *smscconn_name(SMSCConn *conn)
00400 {
00401 gw_assert(conn != NULL);
00402 return conn->name;
00403 }
00404
00405
00406 const Octstr *smscconn_id(SMSCConn *conn)
00407 {
00408 gw_assert(conn != NULL);
00409 return conn->id;
00410 }
00411
00412
00413 int smscconn_usable(SMSCConn *conn, Msg *msg)
00414 {
00415 gw_assert(conn != NULL);
00416 gw_assert(msg != NULL && msg_type(msg) == sms);
00417
00418 if (conn->status == SMSCCONN_DEAD || conn->why_killed != SMSCCONN_ALIVE)
00419 return -1;
00420
00421
00422
00423
00424 if (conn->allowed_smsc_id && (msg->sms.smsc_id == NULL ||
00425 gwlist_search(conn->allowed_smsc_id, msg->sms.smsc_id, octstr_item_match) == NULL)) {
00426 return -1;
00427 }
00428
00429
00430 else if (conn->denied_smsc_id && msg->sms.smsc_id != NULL &&
00431 gwlist_search(conn->denied_smsc_id, msg->sms.smsc_id, octstr_item_match) != NULL) {
00432 return -1;
00433 }
00434
00435 if (conn->allowed_smsc_id_regex) {
00436 if (msg->sms.smsc_id == NULL)
00437 return -1;
00438
00439 if (gw_regex_match_pre(conn->allowed_smsc_id_regex, msg->sms.smsc_id) == 0)
00440 return -1;
00441 }
00442 else if (conn->denied_smsc_id_regex && msg->sms.smsc_id != NULL) {
00443 if (gw_regex_match_pre(conn->denied_smsc_id_regex, msg->sms.smsc_id) == 1)
00444 return -1;
00445 }
00446
00447
00448 if (conn->allowed_prefix && ! conn->denied_prefix &&
00449 (does_prefix_match(conn->allowed_prefix, msg->sms.receiver) != 1))
00450 return -1;
00451
00452 if (conn->allowed_prefix_regex && ! conn->denied_prefix_regex) {
00453 if (gw_regex_match_pre(conn->allowed_prefix_regex, msg->sms.receiver) == 0)
00454 return -1;
00455 }
00456
00457
00458 if (conn->denied_prefix && ! conn->allowed_prefix &&
00459 (does_prefix_match(conn->denied_prefix, msg->sms.receiver) == 1))
00460 return -1;
00461
00462 if (conn->denied_prefix_regex && ! conn->allowed_prefix_regex) {
00463 if (gw_regex_match_pre(conn->denied_prefix_regex, msg->sms.receiver) == 1)
00464 return -1;
00465 }
00466
00467
00468 if (conn->denied_prefix && conn->allowed_prefix &&
00469 (does_prefix_match(conn->allowed_prefix, msg->sms.receiver) != 1) &&
00470 (does_prefix_match(conn->denied_prefix, msg->sms.receiver) == 1) )
00471 return -1;
00472
00473 if (conn->allowed_prefix_regex && conn->denied_prefix_regex) {
00474 if (gw_regex_match_pre(conn->allowed_prefix_regex, msg->sms.receiver) == 0 &&
00475 gw_regex_match_pre(conn->denied_prefix_regex, msg->sms.receiver) == 1)
00476 return -1;
00477 }
00478
00479
00480 if (conn->preferred_smsc_id && msg->sms.smsc_id != NULL &&
00481 gwlist_search(conn->preferred_smsc_id, msg->sms.smsc_id, octstr_item_match) != NULL) {
00482 return 1;
00483 }
00484
00485 if (conn->preferred_prefix)
00486 if (does_prefix_match(conn->preferred_prefix, msg->sms.receiver) == 1)
00487 return 1;
00488
00489 if (conn->preferred_prefix_regex &&
00490 gw_regex_match_pre(conn->preferred_prefix_regex, msg->sms.receiver) == 1) {
00491 return 1;
00492 }
00493
00494 return 0;
00495 }
00496
00497
00498 int smscconn_send(SMSCConn *conn, Msg *msg)
00499 {
00500 int ret = -1;
00501 List *parts = NULL;
00502
00503 gw_assert(conn != NULL);
00504 mutex_lock(conn->flow_mutex);
00505 if (conn->status == SMSCCONN_DEAD || conn->why_killed != SMSCCONN_ALIVE) {
00506 mutex_unlock(conn->flow_mutex);
00507 return -1;
00508 }
00509
00510
00511 if (msg->sms.split_parts == NULL) {
00512
00513 char *uf = conn->unified_prefix ? octstr_get_cstr(conn->unified_prefix) : NULL;
00514 normalize_number(uf, &(msg->sms.receiver));
00515
00516
00517 parts = sms_split(msg, NULL, NULL, NULL, NULL, 1,
00518 counter_increase(split_msg_counter) & 0xff, 0xff, conn->max_sms_octets);
00519 if (gwlist_len(parts) == 1) {
00520
00521 gwlist_destroy(parts, msg_destroy_item);
00522 parts = NULL;
00523 }
00524 }
00525
00526 if (parts == NULL)
00527 ret = conn->send_msg(conn, msg);
00528 else {
00529 long i, parts_len = gwlist_len(parts);
00530 struct split_parts *split = gw_malloc(sizeof(*split));
00531
00532 split->orig = msg_duplicate(msg);
00533 split->parts_left = counter_create();
00534 split->status = SMSCCONN_SUCCESS;
00535 counter_set(split->parts_left, parts_len);
00536 debug("bb.sms.splits", 0, "new split_parts created %p", split);
00537 for (i = 0; i < parts_len; i++) {
00538 msg = gwlist_get(parts, i);
00539 msg->sms.split_parts = split;
00540 ret = conn->send_msg(conn, msg);
00541 if (ret < 0) {
00542 if (i == 0) {
00543 counter_destroy(split->parts_left);
00544 gwlist_destroy(parts, msg_destroy_item);
00545 gw_free(split);
00546 mutex_unlock(conn->flow_mutex);
00547 return ret;
00548 }
00549
00550
00551
00552
00553 split->status = SMSCCONN_FAILED_REJECTED;
00554 counter_increase_with(split->parts_left, -(parts_len - i));
00555 warning(0, "Could not send all parts of a split message");
00556 break;
00557 }
00558 }
00559 gwlist_destroy(parts, msg_destroy_item);
00560 }
00561 mutex_unlock(conn->flow_mutex);
00562 return ret;
00563 }
00564
00565
00566 int smscconn_status(SMSCConn *conn)
00567 {
00568 gw_assert(conn != NULL);
00569
00570 return conn->status;
00571 }
00572
00573
00574 int smscconn_info(SMSCConn *conn, StatusInfo *infotable)
00575 {
00576 if (conn == NULL || infotable == NULL)
00577 return -1;
00578
00579 mutex_lock(conn->flow_mutex);
00580
00581 infotable->status = conn->status;
00582 infotable->killed = conn->why_killed;
00583 infotable->is_stopped = conn->is_stopped;
00584 infotable->online = time(NULL) - conn->connect_time;
00585
00586 infotable->sent = counter_value(conn->sent);
00587 infotable->received = counter_value(conn->received);
00588 infotable->failed = counter_value(conn->failed);
00589
00590 if (conn->queued)
00591 infotable->queued = conn->queued(conn);
00592 else
00593 infotable->queued = -1;
00594
00595 infotable->load = conn->load;
00596
00597 mutex_unlock(conn->flow_mutex);
00598
00599 return 0;
00600 }
00601
00602
See file LICENSE for details about the license agreement for using,
modifying, copying or deriving work from this software.