Kannel: Open Source WAP and SMS gateway  $Revision: 5037 $
bb_smscconn.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2016 Kannel Group
5  * Copyright (c) 1998-2001 WapIT Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Kannel Group (http://www.kannel.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Kannel" and "Kannel Group" must not be used to
28  * endorse or promote products derived from this software without
29  * prior written permission. For written permission, please
30  * contact org@kannel.org.
31  *
32  * 5. Products derived from this software may not be called "Kannel",
33  * nor may "Kannel" appear in their name, without prior written
34  * permission of the Kannel Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Kannel Group. For more information on
51  * the Kannel Group, please see <http://www.kannel.org/>.
52  *
53  * Portions of this software are based upon software originally written at
54  * WapIT Ltd., Helsinki, Finland for the Kannel project.
55  */
56 
57 /*
58  * SMSC Connection interface for Bearerbox.
59  *
60  * Includes callback functions called by SMSCConn implementations
61  *
62  * Handles all startup/shutdown adminstrative work in bearerbox, plus
63  * routing, writing actual access logs, handling failed messages etc.
64  *
65  * Kalle Marjola 2000 for project Kannel
66  * Alexander Malysh <amalysh at kannel.org> 2003, 2004, 2005
67  */
68 
69 #include "gw-config.h"
70 
71 #include <errno.h>
72 #include <stdlib.h>
73 #include <stdio.h>
74 #include <time.h>
75 #include <string.h>
76 #include <sys/time.h>
77 #include <sys/types.h>
78 #include <unistd.h>
79 #include <signal.h>
80 #include <fcntl.h>
81 
82 
83 #include "gwlib/gwlib.h"
84 #include "msg.h"
85 #include "sms.h"
86 #include "bearerbox.h"
87 #include "numhash.h"
88 #include "smscconn.h"
89 #include "dlr.h"
90 #include "load.h"
91 
92 #include "bb_smscconn_cb.h" /* callback functions for connections */
93 #include "smscconn_p.h" /* to access counters */
94 
95 #include "smsc/smpp_pdu.h" /* access smpp_pdu_init/smpp_pdu_shutdown */
96 
97 /* passed from bearerbox core */
98 
99 extern volatile sig_atomic_t bb_status;
100 extern List *incoming_sms;
101 extern List *outgoing_sms;
102 
107 
108 extern Load *outgoing_sms_load;
109 extern Load *incoming_sms_load;
110 extern Load *incoming_dlr_load;
111 extern Load *outgoing_dlr_load;
112 
113 extern List *flow_threads;
114 extern List *suspended;
115 extern List *isolated;
116 
117 /* outgoing sms queue control */
118 extern long max_outgoing_sms_qlength;
119 /* incoming sms queue control */
120 extern long max_incoming_sms_qlength;
121 
122 /* configuration filename */
123 extern Octstr *cfg_filename;
124 
125 /* our own thingies */
126 
127 static volatile sig_atomic_t smsc_running;
128 static List *smsc_list;
133 
143 
144 static regex_t *white_list_sender_regex;
145 static regex_t *black_list_sender_regex;
148 
149 static long router_thread = -1;
150 
151 /* message resend */
153 static long sms_resend_retry;
154 
155 /*
156  * Counter for catenated SMS messages. The counter that can be put into
157  * the catenated SMS message's UDH headers is actually the lowest 8 bits.
158  */
160 
161 /* Flag for handling concatenated incoming messages. */
162 static volatile sig_atomic_t handle_concatenated_mo;
163 /* How long to wait for message parts */
165 /* Flag for return value of check_concat */
167 
168 /*
169  * forward declaration
170  */
171 static long route_incoming_to_smsc(SMSCConn *conn, Msg *msg);
172 
173 static void concat_handling_init(void);
174 static void concat_handling_shutdown(void);
175 static void concat_handling_cleanup(void);
176 static int concat_handling_check_and_handle(Msg **msg, Octstr *smscid);
177 static void concat_handling_clear_old_parts(int force);
178 
179 /*---------------------------------------------------------------------------
180  * CALLBACK FUNCTIONS
181  *
182  * called by SMSCConn implementations when appropriate
183  */
184 
186 {
187  gwlist_add_producer(flow_threads);
188  gwlist_add_producer(incoming_sms);
189 }
190 
191 
193 {
194  if (router_thread >= 0)
196 }
197 
198 
200 {
201  /* NOTE: after status has been set to SMSCCONN_DEAD, bearerbox
202  * is free to release/delete 'conn'
203  */
204  gwlist_remove_producer(incoming_sms);
205  gwlist_remove_producer(flow_threads);
206 }
207 
208 
209 static void handle_split(SMSCConn *conn, Msg *msg, long reason)
210 {
211  struct split_parts *split = msg->sms.split_parts;
212 
213  /*
214  * if the reason is not a success and status is still success
215  * then set status of a split to the reason.
216  * Note: reason 'malformed','discarded' or 'rejected' has higher priority!
217  */
218  switch(reason) {
220  /*
221  * Check if SMSC link alive and if so increase resend_try and set resend_time.
222  * If SMSC link is not active don't increase resend_try and don't set resend_time
223  * because we don't want to delay messages due to broken connection.
224  */
225  if (smscconn_status(conn) == SMSCCONN_ACTIVE) {
226  /*
227  * Check if sms_resend_retry set and this msg has exceeded a limit also
228  * honor "single shot" with sms_resend_retry set to zero.
229  */
230  if (sms_resend_retry >= 0 && msg->sms.resend_try >= sms_resend_retry) {
231  warning(0, "Maximum retries for message exceeded, discarding it!");
233  octstr_create("Retries Exceeded"));
234  return;
235  }
236  msg->sms.resend_try = (msg->sms.resend_try > 0 ? msg->sms.resend_try + 1 : 1);
237  time(&msg->sms.resend_time);
238  }
239  gwlist_produce(outgoing_sms, msg);
240  return;
244  debug("bb.sms.splits", 0, "Set split msg status to %ld", reason);
245  split->status = reason;
246  break;
247  case SMSCCONN_SUCCESS:
248  break; /* nothing todo */
249  default:
250  if (split->status == SMSCCONN_SUCCESS) {
251  debug("bb.sms.splits", 0, "Set split msg status to %ld", reason);
252  split->status = reason;
253  }
254  break;
255  }
256 
257  /*
258  * now destroy this message, because we don't need it anymore.
259  * we will split it again in smscconn_send(...).
260  */
261  msg_destroy(msg);
262 
263  if (counter_decrease(split->parts_left) <= 1) {
264  /* all splited parts were processed */
265  counter_destroy(split->parts_left);
266  msg = split->orig;
267  msg->sms.split_parts = NULL;
268  if (split->status == SMSCCONN_SUCCESS)
269  bb_smscconn_sent(conn, msg, NULL);
270  else {
271  debug("bb.sms.splits", 0, "Parts of concatenated message failed.");
272  bb_smscconn_send_failed(conn, msg, split->status, NULL);
273  }
274  gw_free(split);
275  }
276 }
277 
278 
280 {
281  if (sms->sms.split_parts != NULL) {
282  handle_split(conn, sms, SMSCCONN_SUCCESS);
283  octstr_destroy(reply);
284  return;
285  }
286 
287  /* write ACK to store file */
289 
290  if (sms->sms.sms_type != report_mt) {
291  bb_alog_sms(conn, sms, "Sent SMS");
292  counter_increase(outgoing_sms_counter);
293  load_increase(outgoing_sms_load);
294  if (conn != NULL) {
295  counter_increase(conn->sent);
297  }
298  } else {
299  bb_alog_sms(conn, sms, "Sent DLR");
300  counter_increase(outgoing_dlr_counter);
301  load_increase(outgoing_dlr_load);
302  if (conn != NULL) {
303  counter_increase(conn->sent_dlr);
305  }
306  }
307 
308  /* generate relay confirmancy message */
309  if (DLR_IS_SMSC_SUCCESS(sms->sms.dlr_mask)) {
310  Msg *dlrmsg;
311 
312  if (reply == NULL)
313  reply = octstr_create("");
314 
315  octstr_insert_data(reply, 0, "ACK/", 4);
316  dlrmsg = create_dlr_from_msg((conn->id?conn->id:conn->name), sms,
317  reply, DLR_SMSC_SUCCESS);
318  if (dlrmsg != NULL) {
319  bb_smscconn_receive(conn, dlrmsg);
320  }
321  }
322 
323  msg_destroy(sms);
324  octstr_destroy(reply);
325 }
326 
327 
328 void bb_smscconn_send_failed(SMSCConn *conn, Msg *sms, int reason, Octstr *reply)
329 {
330  if (sms->sms.split_parts != NULL) {
331  handle_split(conn, sms, reason);
332  octstr_destroy(reply);
333  return;
334  }
335 
336  switch (reason) {
338  /*
339  * Check if SMSC link alive and if so increase resend_try and set resend_time.
340  * If SMSC link is not active don't increase resend_try and don't set resend_time
341  * because we don't want to delay messages due to a broken connection.
342  */
343  if (conn && smscconn_status(conn) == SMSCCONN_ACTIVE) {
344  /*
345  * Check if sms_resend_retry set and this msg has exceeded a limit also
346  * honor "single shot" with sms_resend_retry set to zero.
347  */
348  if (sms_resend_retry >= 0 && sms->sms.resend_try >= sms_resend_retry) {
349  warning(0, "Maximum retries for message exceeded, discarding it!");
351  octstr_create("Retries Exceeded"));
352  break;
353  }
354  sms->sms.resend_try = (sms->sms.resend_try > 0 ? sms->sms.resend_try + 1 : 1);
355  time(&sms->sms.resend_time);
356  }
357  gwlist_produce(outgoing_sms, sms);
358  break;
359 
361  gwlist_produce(outgoing_sms, sms);
362  break;
363 
364  default:
365  /* write NACK to store file */
367 
368  if (conn) counter_increase(conn->failed);
369  if (reason == SMSCCONN_FAILED_DISCARDED) {
370  if (sms->sms.sms_type != report_mt)
371  bb_alog_sms(conn, sms, "DISCARDED SMS");
372  else
373  bb_alog_sms(conn, sms, "DISCARDED DLR");
374  }
375  else if (reason == SMSCCONN_FAILED_EXPIRED) {
376  if (sms->sms.sms_type != report_mt)
377  bb_alog_sms(conn, sms, "EXPIRED SMS");
378  else
379  bb_alog_sms(conn, sms, "EXPIRED DLR");
380  }
381  else if (reason == SMSCCONN_FAILED_REJECTED) {
382  if (sms->sms.sms_type != report_mt)
383  bb_alog_sms(conn, sms, "REJECTED Send SMS");
384  else
385  bb_alog_sms(conn, sms, "REJECTED Send DLR");
386  }
387  else {
388  if (sms->sms.sms_type != report_mt)
389  bb_alog_sms(conn, sms, "FAILED Send SMS");
390  else
391  bb_alog_sms(conn, sms, "FAILED Send DLR");
392  }
393 
394  /* generate relay confirmancy message */
395  if (DLR_IS_SMSC_FAIL(sms->sms.dlr_mask) ||
396  DLR_IS_FAIL(sms->sms.dlr_mask)) {
397  Msg *dlrmsg;
398 
399  if (reply == NULL)
400  reply = octstr_create("");
401 
402  octstr_insert_data(reply, 0, "NACK/", 5);
403  dlrmsg = create_dlr_from_msg((conn ? (conn->id?conn->id:conn->name) : NULL), sms,
404  reply, DLR_SMSC_FAIL);
405  if (dlrmsg != NULL) {
406  bb_smscconn_receive(conn, dlrmsg);
407  }
408  }
409 
410  msg_destroy(sms);
411  break;
412  }
413 
414  octstr_destroy(reply);
415 }
416 
417 static long bb_smscconn_receive_internal(SMSCConn *conn, Msg *sms)
418 {
419  int rc;
420  Msg *copy;
421 
422  copy = msg_duplicate(sms);
423 
424  /*
425  * Try to reroute internally to an smsc-id without leaving
426  * actually bearerbox scope.
427  * Scope: internal routing (to smsc-ids)
428  */
429  if ((rc = route_incoming_to_smsc(conn, copy)) == -1) {
430  /*
431  * Now try to route the message to a specific smsbox
432  * connection based on the existing msg->sms.boxc_id or
433  * the registered receiver numbers for specific smsbox'es.
434  * Scope: external routing (to smsbox connections)
435  */
436  rc = route_incoming_to_boxc(copy);
437  }
438 
439  if (rc == -1 || (rc != SMSCCONN_SUCCESS && rc != SMSCCONN_QUEUED)) {
440  warning(0, "incoming messages queue too long, dropping a message");
441  if (sms->sms.sms_type == report_mo)
442  bb_alog_sms(conn, sms, "DROPPED Received DLR");
443  else
444  bb_alog_sms(conn, sms, "DROPPED Received SMS");
445 
446  /* put nack into store-file */
448 
449  msg_destroy(copy);
450  msg_destroy(sms);
451  gwthread_sleep(0.1); /* letting the queue go down */
452  return (rc == -1 ? SMSCCONN_FAILED_QFULL : rc);
453  }
454 
455  if (sms->sms.sms_type != report_mo) {
456  bb_alog_sms(conn, sms, "Receive SMS");
457  counter_increase(incoming_sms_counter);
458  load_increase(incoming_sms_load);
459  if (conn != NULL) {
460  counter_increase(conn->received);
462  }
463  } else {
464  bb_alog_sms(conn, sms, "Receive DLR");
465  counter_increase(incoming_dlr_counter);
466  load_increase(incoming_dlr_load);
467  if (conn != NULL) {
470  }
471  }
472 
473  msg_destroy(sms);
474 
475  return SMSCCONN_SUCCESS;
476 }
477 
479 {
480  char *uf;
481  int ret;
482 
483  /*
484  * first check whether msgdata data is NULL and set it to empty
485  * because seems too much kannels parts rely on msgdata not to be NULL.
486  */
487  if (sms->sms.msgdata == NULL)
488  sms->sms.msgdata = octstr_create("");
489 
490  /*
491  * First normalize in smsc level and then on global level.
492  * In outbound direction it's vise versa, hence first global then smsc.
493  */
494  uf = (conn && conn->unified_prefix) ? octstr_get_cstr(conn->unified_prefix) : NULL;
495  normalize_number(uf, &(sms->sms.sender));
496 
497  uf = unified_prefix ? octstr_get_cstr(unified_prefix) : NULL;
498  normalize_number(uf, &(sms->sms.sender));
499 
500  /*
501  * We don't perform white/black-listing for DLRs.
502  * Fix sms type if not set already.
503  */
504  if (sms->sms.sms_type != report_mo) {
505  sms->sms.sms_type = mo;
506 
507  gw_rwlock_rdlock(&white_black_list_lock);
508  if (white_list_sender &&
509  numhash_find_number(white_list_sender, sms->sms.sender) < 1) {
510  gw_rwlock_unlock(&white_black_list_lock);
511  info(0, "Number <%s> is not in white-list, message discarded",
512  octstr_get_cstr(sms->sms.sender));
513  bb_alog_sms(conn, sms, "REJECTED Receive SMS - not white-listed SMS");
514  msg_destroy(sms);
516  }
517 
519  gw_regex_match_pre(white_list_sender_regex, sms->sms.sender) == 0) {
520  gw_rwlock_unlock(&white_black_list_lock);
521  info(0, "Number <%s> is not in white-list, message discarded",
522  octstr_get_cstr(sms->sms.sender));
523  bb_alog_sms(conn, sms, "REJECTED Receive SMS - not white-regex-listed SMS");
524  msg_destroy(sms);
526  }
527 
528  if (black_list_sender &&
529  numhash_find_number(black_list_sender, sms->sms.sender) == 1) {
530  gw_rwlock_unlock(&white_black_list_lock);
531  info(0, "Number <%s> is in black-list, message discarded",
532  octstr_get_cstr(sms->sms.sender));
533  bb_alog_sms(conn, sms, "REJECTED Receive SMS - black-listed SMS");
534  msg_destroy(sms);
536  }
537 
539  gw_regex_match_pre(black_list_sender_regex, sms->sms.sender) == 0) {
540  gw_rwlock_unlock(&white_black_list_lock);
541  info(0, "Number <%s> is not in black-list, message discarded",
542  octstr_get_cstr(sms->sms.sender));
543  bb_alog_sms(conn, sms, "REJECTED Receive SMS - black-regex-listed SMS");
544  msg_destroy(sms);
546  }
547 
548  if (white_list_receiver &&
549  numhash_find_number(white_list_receiver, sms->sms.receiver) < 1) {
550  gw_rwlock_unlock(&white_black_list_lock);
551  info(0, "Number <%s> is not in white-list-receiver, message discarded",
552  octstr_get_cstr(sms->sms.receiver));
553  bb_alog_sms(conn, sms, "REJECTED Receive SMS - not white-listed SMS");
554  msg_destroy(sms);
556  }
557 
559  gw_regex_match_pre(white_list_receiver_regex, sms->sms.receiver) == 0) {
560  gw_rwlock_unlock(&white_black_list_lock);
561  info(0, "Number <%s> is not in white-list-receiver, message discarded",
562  octstr_get_cstr(sms->sms.receiver));
563  bb_alog_sms(conn, sms, "REJECTED Receive SMS - not white-regex-listed SMS");
564  msg_destroy(sms);
566  }
567 
568  if (black_list_receiver &&
569  numhash_find_number(black_list_receiver, sms->sms.receiver) == 1) {
570  gw_rwlock_unlock(&white_black_list_lock);
571  info(0, "Number <%s> is in black-list-receiver, message discarded",
572  octstr_get_cstr(sms->sms.receiver));
573  bb_alog_sms(conn, sms, "REJECTED Receive SMS - black-listed SMS");
574  msg_destroy(sms);
576  }
577 
579  gw_regex_match_pre(black_list_receiver_regex, sms->sms.receiver) == 0) {
580  gw_rwlock_unlock(&white_black_list_lock);
581  info(0, "Number <%s> is not in black-list-receiver, message discarded",
582  octstr_get_cstr(sms->sms.receiver));
583  bb_alog_sms(conn, sms, "REJECTED Receive SMS - black-regex-listed SMS");
584  msg_destroy(sms);
586  }
587  gw_rwlock_unlock(&white_black_list_lock);
588  }
589 
590  /* write to store (if enabled) */
591  if (store_save(sms) == -1) {
592  msg_destroy(sms);
594  }
595 
596  /* Before routing to some box or re-routing, do concatenation handling
597  * and replace copy as such.
598  */
599  if (handle_concatenated_mo && sms->sms.sms_type == mo) {
600  ret = concat_handling_check_and_handle(&sms, (conn ? conn->id : NULL));
601  switch(ret) {
602  case concat_pending:
603  counter_increase(incoming_sms_counter); /* ?? */
604  load_increase(incoming_sms_load);
605  if (conn != NULL) {
606  counter_increase(conn->received);
608  }
609  return SMSCCONN_SUCCESS;
610  case concat_complete:
611  /* Combined sms received! save new one since it is now combined. */
612  break;
613  case concat_error:
614  /* failed to save, go away. */
615  msg_destroy(sms);
617  case concat_none:
618  break;
619  default:
620  panic(0, "Internal error: Unhandled concat result.");
621  break;
622  }
623  }
624 
625  return bb_smscconn_receive_internal(conn, sms);
626 }
627 
629 {
630  debug("bb.sms", 0, "Reloading smsc groups list from config resource");
631  cfg_destroy(cfg_reloaded);
632  cfg_reloaded = cfg_create(cfg_filename);
633  if (cfg_read(cfg_reloaded) == -1) {
634  warning(0, "Error opening configuration file %s", octstr_get_cstr(cfg_filename));
635  return -1;
636  }
637  gwlist_destroy(smsc_groups, NULL);
638  smsc_groups = cfg_get_multi_group(cfg_reloaded, octstr_imm("smsc"));
639 
640  return 0;
641 }
642 
643 
644 /*---------------------------------------------------------------------
645  * Other functions
646  */
647 
648 /* function to route outgoing SMS'es from delay-list
649  * use some nice magics to route them to proper SMSC
650  */
651 static void sms_router(void *arg)
652 {
653  Msg *msg, *startmsg, *newmsg;
654  long ret;
655  time_t concat_mo_check;
656 
657  gwlist_add_producer(flow_threads);
659 
660  startmsg = newmsg = NULL;
661  ret = SMSCCONN_SUCCESS;
662  concat_mo_check = time(NULL);
663 
664  while(bb_status != BB_SHUTDOWN && bb_status != BB_DEAD) {
665 
666  if (newmsg == startmsg) {
667  if (ret == SMSCCONN_QUEUED || ret == SMSCCONN_FAILED_QFULL) {
668  /* sleep: sms_resend_frequency / 2 , so we reduce amount of msgs to send */
669  double sleep_time = (sms_resend_frequency / 2 > 1 ? sms_resend_frequency / 2 : sms_resend_frequency);
670  debug("bb.sms", 0, "sms_router: time to sleep %.2f secs.", sleep_time);
671  gwthread_sleep(sleep_time);
672  debug("bb.sms", 0, "sms_router: gwlist_len = %ld", gwlist_len(outgoing_sms));
673  }
674  startmsg = msg = gwlist_timed_consume(outgoing_sms, concatenated_mo_timeout);
675  newmsg = NULL;
676  } else {
677  newmsg = msg = gwlist_timed_consume(outgoing_sms, concatenated_mo_timeout);
678  }
679 
680  if (difftime(time(NULL), concat_mo_check) > concatenated_mo_timeout) {
681  concat_mo_check = time(NULL);
683  }
684 
685  /* shutdown or timeout */
686  if (msg == NULL) {
687  newmsg = startmsg = NULL;
688  continue;
689  }
690 
691  debug("bb.sms", 0, "sms_router: handling message (%p vs %p)",
692  msg, startmsg);
693 
694  /* handle delayed msgs */
695  if (msg->sms.resend_try > 0 && difftime(time(NULL), msg->sms.resend_time) < sms_resend_frequency &&
697  debug("bb.sms", 0, "re-queing SMS not-yet-to-be resent");
698  gwlist_produce(outgoing_sms, msg);
699  ret = SMSCCONN_QUEUED;
700  continue;
701  }
702 
703  ret = smsc2_rout(msg, 1);
704  switch(ret) {
705  case SMSCCONN_SUCCESS:
706  debug("bb.sms", 0, "Message routed successfully.");
707  newmsg = startmsg = NULL;
708  break;
709  case SMSCCONN_QUEUED:
710  debug("bb.sms", 0, "Routing failed, re-queued.");
711  break;
713  msg_destroy(msg);
714  newmsg = startmsg = NULL;
715  break;
717  debug("bb.sms", 0, "Routing failed, re-queuing.");
718  gwlist_produce(outgoing_sms, msg);
719  break;
721  debug("bb.sms", 0, "Routing failed, expired.");
722  msg_destroy(msg);
723  newmsg = startmsg = NULL;
724  break;
725  default:
726  break;
727  }
728  }
729  gwlist_remove_producer(flow_threads);
730 }
731 
732 
733 #define OCTSTR(os) octstr_imm(#os)
734 
735 static int cmp_conn_grp_checksum(void *a, void *b)
736 {
737  int ret;
738  SMSCConn *conn = a;
739  Octstr *os;
740 
742  NULL
743  );
744 
745  ret = (octstr_compare(conn->chksum, os) == 0);
746  octstr_destroy(os);
747 
748  return ret;
749 }
750 
751 
752 static int cmp_rout_grp_checksum(void *a, void *b)
753 {
754  int ret;
755  SMSCConn *conn = a;
756  Octstr *os;
757 
759  OCTSTR(denied-smsc-id),
760  OCTSTR(allowed-smsc-id),
761  OCTSTR(preferred-smsc-id),
762  OCTSTR(allowed-prefix),
763  OCTSTR(denied-prefix),
764  OCTSTR(preferred-prefix),
765  OCTSTR(unified-prefix),
766  OCTSTR(reroute),
767  OCTSTR(reroute-smsc-id),
768  OCTSTR(reroute-receiver),
769  OCTSTR(reroute-dlr),
770  OCTSTR(allowed-smsc-id-regex),
771  OCTSTR(denied-smsc-id-regex),
772  OCTSTR(preferred-smsc-id-regex),
773  OCTSTR(allowed-prefix-regex),
774  OCTSTR(denied-prefix-regex),
775  OCTSTR(preferred-prefix-regex),
776  NULL
777  );
778 
779  ret = (octstr_compare(conn->chksum_conn, os) == 0);
780  octstr_destroy(os);
781 
782  return ret;
783 }
784 
785 #undef OCTSTR
786 
787 
788 static int cmp_conn_grp_id(void *a, void *b)
789 {
790  int ret;
791  SMSCConn *conn = a;
792  Octstr *os = cfg_get((CfgGroup*)b, octstr_imm("smsc-id"));
793 
794  ret = (os && octstr_compare(conn->id, os) == 0);
795  octstr_destroy(os);
796 
797  return ret;
798 }
799 
800 
801 /*-------------------------------------------------------------
802  * public functions
803  *
804  */
805 
807 {
808  CfgGroup *grp;
809  SMSCConn *conn;
810  Octstr *os;
811  int i, j, m;
812 
813  if (smsc_running) return -1;
814 
815  /* at start-up time there is no reloaded config */
816  cfg_reloaded = NULL;
817 
818  /* create split sms counter */
819  split_msg_counter = counter_create();
820 
821  /* create smsc list and rwlock for it */
822  smsc_list = gwlist_create();
823  gw_rwlock_init_static(&smsc_list_lock);
824 
825  grp = cfg_get_single_group(cfg, octstr_imm("core"));
826  unified_prefix = cfg_get(grp, octstr_imm("unified-prefix"));
827 
828  gw_rwlock_init_static(&white_black_list_lock);
829  white_list_sender = black_list_sender = NULL;
830  white_list_sender_url = black_list_sender_url = NULL;
831  if ((white_list_sender_url = cfg_get(grp, octstr_imm("white-list"))) != NULL) /* TODO deprecated, remove */
832  warning(0, "Option 'white-list' is deprecated! Please use 'white-list-sender' instead!");
833  else
834  white_list_sender_url = cfg_get(grp, octstr_imm("white-list-sender"));
835  if (white_list_sender_url != NULL) {
836  if ((white_list_sender = numhash_create(octstr_get_cstr(white_list_sender_url))) == NULL)
837  panic(0, "Could not get white-list at URL <%s>",
838  octstr_get_cstr(white_list_sender_url));
839  }
840  if ((os = cfg_get(grp, octstr_imm("white-list-regex"))) != NULL) /* TODO deprecated, remove */
841  warning(0, "Option 'white-list-regex' is deprecated! Please use 'white-list-sender-regex' instead!");
842  else
843  os = cfg_get(grp, octstr_imm("white-list-sender-regex"));
844  if (os != NULL) {
845  if ((white_list_sender_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
846  panic(0, "Could not compile pattern '%s'", octstr_get_cstr(os));
847  octstr_destroy(os);
848  }
849 
850  if ((black_list_sender_url = cfg_get(grp, octstr_imm("black-list"))) != NULL) /* TODO deprecated, remove */
851  warning(0, "Option 'black-list' is deprecated! Please use 'black-list-sender' instead!");
852  else
853  black_list_sender_url = cfg_get(grp, octstr_imm("black-list-sender"));
854  if (black_list_sender_url != NULL) {
855  if ((black_list_sender = numhash_create(octstr_get_cstr(black_list_sender_url))) == NULL)
856  panic(0, "Could not get black-list at URL <%s>",
857  octstr_get_cstr(black_list_sender_url));
858  }
859  if ((os = cfg_get(grp, octstr_imm("black-list-regex"))) != NULL) /* TODO deprecated, remove */
860  warning(0, "Option 'black-list-regex' is deprecated! Please use 'black-list-sender-regex' instead!");
861  else
862  os = cfg_get(grp, octstr_imm("black-list-sender-regex"));
863  if (os != NULL) {
864  if ((black_list_sender_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
865  panic(0, "Could not compile pattern '%s'", octstr_get_cstr(os));
866  octstr_destroy(os);
867  }
868 
869  white_list_receiver = black_list_receiver = NULL;
870  white_list_receiver_url = black_list_receiver_url = NULL;
871  white_list_receiver_url = cfg_get(grp, octstr_imm("white-list-receiver"));
872  if (white_list_receiver_url != NULL) {
873  if ((white_list_receiver = numhash_create(octstr_get_cstr(white_list_receiver_url))) == NULL)
874  panic(0, "Could not get white-list-receiver at URL <%s>",
875  octstr_get_cstr(white_list_receiver_url));
876  }
877  if ((os = cfg_get(grp, octstr_imm("white-list-receiver-regex"))) != NULL) {
878  if ((white_list_receiver_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
879  panic(0, "Could not compile pattern '%s'", octstr_get_cstr(os));
880  octstr_destroy(os);
881  }
882 
883  black_list_receiver_url = cfg_get(grp, octstr_imm("black-list-receiver"));
884  if (black_list_receiver_url != NULL) {
885  if ((black_list_receiver = numhash_create(octstr_get_cstr(black_list_receiver_url))) == NULL)
886  panic(0, "Could not get black-list-receiver at URL <%s>",
887  octstr_get_cstr(black_list_receiver_url));
888  }
889  if ((os = cfg_get(grp, octstr_imm("black-list-receiver-regex"))) != NULL) {
890  if ((black_list_receiver_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
891  panic(0, "Could not compile pattern '%s'", octstr_get_cstr(os));
892  octstr_destroy(os);
893  }
894 
896  octstr_imm("sms-resend-freq")) == -1 || sms_resend_frequency <= 0) {
898  }
899  info(0, "Set SMS resend frequency to %ld seconds.", sms_resend_frequency);
900 
901  if (cfg_get_integer(&sms_resend_retry, grp, octstr_imm("sms-resend-retry")) == -1) {
902  sms_resend_retry = -1;
903  info(0, "SMS resend retry set to unlimited.");
904  }
905  else
906  info(0, "SMS resend retry set to %ld.", sms_resend_retry);
907 
908  if (cfg_get_bool((int*)&handle_concatenated_mo, grp, octstr_imm("sms-combine-concatenated-mo")) == -1)
909  handle_concatenated_mo = 1; /* default is TRUE. */
910 
911  if (cfg_get_integer(&concatenated_mo_timeout, grp, octstr_imm("sms-combine-concatenated-mo-timeout")) == -1)
913 
916 
917  /* initialize low level PDUs */
918  if (smpp_pdu_init(cfg) == -1)
919  panic(0, "Connot start with PDU init failed.");
920 
921  smsc_groups = cfg_get_multi_group(cfg, octstr_imm("smsc"));
922  gwlist_add_producer(smsc_list);
923  for (i = 0; i < gwlist_len(smsc_groups) &&
924  (grp = gwlist_get(smsc_groups, i)) != NULL; i++) {
925  /* multiple instances for the same group? */
926  m = smscconn_instances(grp);
927  for (j = 0; j < m; j++) {
928  conn = smscconn_create(grp, 1);
929  if (conn == NULL)
930  panic(0, "Cannot start with SMSC connection failing");
931  gwlist_append(smsc_list, conn);
932  }
933  }
934  gwlist_remove_producer(smsc_list);
935 
936  if ((router_thread = gwthread_create(sms_router, NULL)) == -1)
937  panic(0, "Failed to start a new thread for SMS routing");
938 
939  gwlist_add_producer(incoming_sms);
940  smsc_running = 1;
941  return 0;
942 }
943 
944 /*
945  * Find a matching smsc-id in the smsc list starting at position start.
946  * NOTE: Caller must ensure that smsc_list is properly locked!
947  */
948 static long smsc2_find(Octstr *id, long start)
949 {
950  SMSCConn *conn = NULL;
951  long i;
952 
953  if (start > gwlist_len(smsc_list) || start < 0 || id == NULL)
954  return -1;
955 
956  for (i = start; i < gwlist_len(smsc_list); i++) {
957  conn = gwlist_get(smsc_list, i);
958  if (conn != NULL && conn->admin_id != NULL && octstr_compare(conn->admin_id, id) == 0) {
959  break;
960  }
961  }
962  if (i >= gwlist_len(smsc_list))
963  i = -1;
964 
965  return i;
966 }
967 
969 {
970  SMSCConn *conn;
971  long i = -1;
972  int success = 0;
973 
974  if (!smsc_running)
975  return -1;
976 
977  gw_rwlock_rdlock(&smsc_list_lock);
978  /* find the specific smsc via id */
979  while((i = smsc2_find(id, ++i)) != -1) {
980  conn = gwlist_get(smsc_list, i);
981  if (conn != NULL && smscconn_status(conn) == SMSCCONN_DEAD) {
982  info(0, "HTTP: Could not shutdown already dead smsc-id `%s'",
983  octstr_get_cstr(id));
984  } else {
985  info(0,"HTTP: Shutting down smsc-id `%s'", octstr_get_cstr(id));
986  smscconn_shutdown(conn, 1); /* shutdown the smsc */
987  success = 1;
988  }
989  }
990  gw_rwlock_unlock(&smsc_list_lock);
991  if (success == 0) {
992  error(0, "SMSC %s not found", octstr_get_cstr(id));
993  return -1;
994  }
995  return 0;
996 }
997 
999 {
1000  CfgGroup *grp;
1001  SMSCConn *conn, *new_conn;
1002  Octstr *smscid = NULL;
1003  long i = -1;
1004  int hit;
1005  int num = 0;
1006  int success = 0;
1007 
1008  if (!smsc_running)
1009  return -1;
1010 
1011  gw_rwlock_wrlock(&smsc_list_lock);
1012 
1013  if (bb_reload_smsc_groups() != 0) {
1014  gw_rwlock_unlock(&smsc_list_lock);
1015  return -1;
1016  }
1017  /* find the specific smsc via id */
1018  while((i = smsc2_find(id, ++i)) != -1) {
1019  long group_index;
1020  /* check if smsc has online status already */
1021  conn = gwlist_get(smsc_list, i);
1022  if (conn != NULL && smscconn_status(conn) != SMSCCONN_DEAD) {
1023  warning(0, "HTTP: Could not re-start already running smsc-id `%s'",
1024  octstr_get_cstr(id));
1025  continue;
1026  }
1027  /* find the group with equal smsc (admin-)id */
1028  hit = -1;
1029  grp = NULL;
1030  for (group_index = 0; group_index < gwlist_len(smsc_groups) &&
1031  (grp = gwlist_get(smsc_groups, group_index)) != NULL; group_index++) {
1032  smscid = cfg_get(grp, octstr_imm("smsc-admin-id"));
1033  if (smscid == NULL)
1034  smscid = cfg_get(grp, octstr_imm("smsc-id"));
1035  if (smscid != NULL && octstr_compare(smscid, id) == 0) {
1036  if (hit < 0)
1037  hit = 0;
1038  if (hit == num)
1039  break;
1040  else
1041  hit++;
1042  }
1043  octstr_destroy(smscid);
1044  smscid = NULL;
1045  }
1046  octstr_destroy(smscid);
1047  if (hit != num) {
1048  /* config group not found */
1049  error(0, "HTTP: Could not find config for smsc-id `%s'", octstr_get_cstr(id));
1050  break;
1051  }
1052 
1053  info(0,"HTTP: Re-starting smsc-id `%s'", octstr_get_cstr(id));
1054 
1055  new_conn = smscconn_create(grp, 1);
1056  if (new_conn == NULL) {
1057  error(0, "Start of SMSC connection failed, smsc-id `%s'", octstr_get_cstr(id));
1058  continue; /* keep old connection on the list */
1059  }
1060 
1061  /* drop old connection from the active smsc list */
1062  gwlist_delete(smsc_list, i, 1);
1063  /* destroy the connection */
1064  smscconn_destroy(conn);
1065  gwlist_insert(smsc_list, i, new_conn);
1066  smscconn_start(new_conn);
1067  success = 1;
1068  num++;
1069  }
1070 
1071  gw_rwlock_unlock(&smsc_list_lock);
1072 
1073  if (success == 0) {
1074  error(0, "SMSC %s not found", octstr_get_cstr(id));
1075  return -1;
1076  }
1077  /* wake-up the router */
1078  if (router_thread >= 0)
1080  return 0;
1081 }
1082 
1084 {
1085  SMSCConn *conn;
1086  long i = -1;
1087  int success = 0;
1088 
1089  if (!smsc_running)
1090  return -1;
1091 
1092  gw_rwlock_wrlock(&smsc_list_lock);
1093 
1094  gwlist_add_producer(smsc_list);
1095  while((i = smsc2_find(id, ++i)) != -1) {
1096  conn = gwlist_get(smsc_list, i);
1097  gwlist_delete(smsc_list, i, 1);
1098  smscconn_shutdown(conn, 0);
1099  smscconn_destroy(conn);
1100  success = 1;
1101  }
1102  gwlist_remove_producer(smsc_list);
1103 
1104  gw_rwlock_unlock(&smsc_list_lock);
1105  if (success == 0) {
1106  error(0, "SMSC %s not found", octstr_get_cstr(id));
1107  return -1;
1108  }
1109  return 0;
1110 }
1111 
1113 {
1114  CfgGroup *grp;
1115  SMSCConn *conn;
1116  Octstr *smscid = NULL;
1117  long i;
1118  int success = 0;
1119 
1120  if (!smsc_running)
1121  return -1;
1122 
1123  gw_rwlock_wrlock(&smsc_list_lock);
1124  if (bb_reload_smsc_groups() != 0) {
1125  gw_rwlock_unlock(&smsc_list_lock);
1126  return -1;
1127  }
1128 
1129  if (smsc2_find(id, 0) != -1) {
1130  warning(0, "Could not add already existing SMSC %s", octstr_get_cstr(id));
1131  gw_rwlock_unlock(&smsc_list_lock);
1132  return -1;
1133  }
1134 
1135  gwlist_add_producer(smsc_list);
1136  grp = NULL;
1137  for (i = 0; i < gwlist_len(smsc_groups) &&
1138  (grp = gwlist_get(smsc_groups, i)) != NULL; i++) {
1139  smscid = cfg_get(grp, octstr_imm("smsc-admin-id"));
1140  if (smscid == NULL)
1141  smscid = cfg_get(grp, octstr_imm("smsc-id"));
1142 
1143  if (smscid != NULL && octstr_compare(smscid, id) == 0) {
1144  conn = smscconn_create(grp, 1);
1145  if (conn != NULL) {
1146  gwlist_append(smsc_list, conn);
1147  if (conn->dead_start) {
1148  /* Shutdown connection if it's not configured to connect at start-up time */
1149  smscconn_shutdown(conn, 0);
1150  } else {
1151  smscconn_start(conn);
1152  }
1153  success = 1;
1154  }
1155  }
1156  }
1157  gwlist_remove_producer(smsc_list);
1158  gw_rwlock_unlock(&smsc_list_lock);
1159  if (success == 0) {
1160  error(0, "SMSC %s not found", octstr_get_cstr(id));
1161  return -1;
1162  }
1163  return 0;
1164 }
1165 
1167 {
1168  Numhash *tmp;
1169  int rc = 1;
1170 
1171  if (white_list_sender_url != NULL) {
1172  tmp = numhash_create(octstr_get_cstr(white_list_sender_url));
1173  if (white_list_sender == NULL) {
1174  error(0, "Unable to reload white_list."),
1175  rc = -1;
1176  } else {
1177  gw_rwlock_wrlock(&white_black_list_lock);
1178  numhash_destroy(white_list_sender);
1179  white_list_sender = tmp;
1180  gw_rwlock_unlock(&white_black_list_lock);
1181  }
1182  }
1183 
1184  if (black_list_sender_url != NULL) {
1185  tmp = numhash_create(octstr_get_cstr(black_list_sender_url));
1186  if (black_list_sender == NULL) {
1187  error(0, "Unable to reload black_list");
1188  rc = -1;
1189  } else {
1190  gw_rwlock_wrlock(&white_black_list_lock);
1191  numhash_destroy(black_list_sender);
1192  black_list_sender = tmp;
1193  gw_rwlock_unlock(&white_black_list_lock);
1194  }
1195  }
1196 
1197  if (white_list_receiver_url != NULL) {
1198  tmp = numhash_create(octstr_get_cstr(white_list_receiver_url));
1199  if (white_list_receiver == NULL) {
1200  error(0, "Unable to reload white_list."),
1201  rc = -1;
1202  } else {
1203  gw_rwlock_wrlock(&white_black_list_lock);
1204  numhash_destroy(white_list_receiver);
1205  white_list_receiver = tmp;
1206  gw_rwlock_unlock(&white_black_list_lock);
1207  }
1208  }
1209 
1210  if (black_list_receiver_url != NULL) {
1211  tmp = numhash_create(octstr_get_cstr(black_list_receiver_url));
1212  if (black_list_receiver == NULL) {
1213  error(0, "Unable to reload black_list");
1214  rc = -1;
1215  } else {
1216  gw_rwlock_wrlock(&white_black_list_lock);
1217  numhash_destroy(black_list_receiver);
1218  black_list_sender = tmp;
1219  gw_rwlock_unlock(&white_black_list_lock);
1220  }
1221  }
1222 
1223  return rc;
1224 }
1225 
1226 void smsc2_resume(int is_init)
1227 {
1228  SMSCConn *conn;
1229  long i;
1230 
1231  if (!smsc_running)
1232  return;
1233 
1234  gw_rwlock_rdlock(&smsc_list_lock);
1235  for (i = 0; i < gwlist_len(smsc_list); i++) {
1236  conn = gwlist_get(smsc_list, i);
1237  if (!is_init || !conn->dead_start) {
1238  smscconn_start(conn);
1239  } else {
1240  /* Shutdown the connections that are not configured to start at boot */
1241  smscconn_shutdown(conn, 0);
1242  }
1243  }
1244  gw_rwlock_unlock(&smsc_list_lock);
1245 
1246  if (router_thread >= 0)
1248 }
1249 
1250 
1251 void smsc2_suspend(void)
1252 {
1253  SMSCConn *conn;
1254  long i;
1255 
1256  if (!smsc_running)
1257  return;
1258 
1259  gw_rwlock_rdlock(&smsc_list_lock);
1260  for (i = 0; i < gwlist_len(smsc_list); i++) {
1261  conn = gwlist_get(smsc_list, i);
1262  smscconn_stop(conn);
1263  }
1264  gw_rwlock_unlock(&smsc_list_lock);
1265 }
1266 
1267 
1269 {
1270  SMSCConn *conn;
1271  long i;
1272 
1273  if (!smsc_running)
1274  return -1;
1275 
1276  /* stop concat handling */
1278 
1279  /* Call shutdown for all SMSC Connections; they should
1280  * handle that they quit, by emptying queues and then dying off
1281  */
1282  gw_rwlock_rdlock(&smsc_list_lock);
1283  for(i=0; i < gwlist_len(smsc_list); i++) {
1284  conn = gwlist_get(smsc_list, i);
1285  smscconn_shutdown(conn, 1);
1286  }
1287  gw_rwlock_unlock(&smsc_list_lock);
1288  if (router_thread >= 0)
1290 
1291  /* start avalanche by calling shutdown */
1292 
1293  /* XXX shouldn'w we be sure that all smsces have closed their
1294  * receive thingies? Is this guaranteed by setting bb_status
1295  * to shutdown before calling these?
1296  */
1297  gwlist_remove_producer(incoming_sms);
1298 
1299  /* shutdown low levele PDU things */
1301 
1302  return 0;
1303 }
1304 
1305 
1306 void smsc2_cleanup(void)
1307 {
1308  SMSCConn *conn;
1309  long i;
1310 
1311  if (!smsc_running)
1312  return;
1313 
1314  debug("smscconn", 0, "final clean-up for SMSCConn");
1315 
1316  gw_rwlock_wrlock(&smsc_list_lock);
1317  for (i = 0; i < gwlist_len(smsc_list); i++) {
1318  conn = gwlist_get(smsc_list, i);
1319  smscconn_destroy(conn);
1320  }
1321  gwlist_destroy(smsc_list, NULL);
1322  smsc_list = NULL;
1323  gw_rwlock_unlock(&smsc_list_lock);
1324  gwlist_destroy(smsc_groups, NULL);
1325  octstr_destroy(unified_prefix);
1326  numhash_destroy(white_list_sender);
1327  numhash_destroy(black_list_sender);
1328  octstr_destroy(white_list_sender_url);
1329  octstr_destroy(black_list_sender_url);
1330  if (white_list_sender_regex != NULL)
1331  gw_regex_destroy(white_list_sender_regex);
1332  if (black_list_sender_regex != NULL)
1333  gw_regex_destroy(black_list_sender_regex);
1334  numhash_destroy(white_list_receiver);
1335  numhash_destroy(black_list_receiver);
1336  octstr_destroy(white_list_receiver_url);
1337  octstr_destroy(black_list_receiver_url);
1338  if (white_list_receiver_regex != NULL)
1339  gw_regex_destroy(white_list_receiver_regex);
1340  if (black_list_receiver_regex != NULL)
1341  gw_regex_destroy(black_list_receiver_regex);
1342  /* destroy msg split counter */
1343  counter_destroy(split_msg_counter);
1344  gw_rwlock_destroy(&smsc_list_lock);
1345  gw_rwlock_destroy(&white_black_list_lock);
1346 
1347  /* Stop concat handling */
1349 
1350  smsc_running = 0;
1351 }
1352 
1353 
1354 Octstr *smsc2_status(int status_type)
1355 {
1356  Octstr *tmp;
1357  char tmp3[64];
1358  char *lb;
1359  long i;
1360  int para = 0;
1361  SMSCConn *conn;
1362  StatusInfo info;
1363  const Octstr *conn_id = NULL;
1364  const Octstr *conn_admin_id = NULL;
1365  const Octstr *conn_name = NULL;
1366  float incoming_sms_load_0, incoming_sms_load_1, incoming_sms_load_2;
1367  float outgoing_sms_load_0, outgoing_sms_load_1, outgoing_sms_load_2;
1368  float incoming_dlr_load_0, incoming_dlr_load_1, incoming_dlr_load_2;
1369  float outgoing_dlr_load_0, outgoing_dlr_load_1, outgoing_dlr_load_2;
1370 
1371  if ((lb = bb_status_linebreak(status_type)) == NULL)
1372  return octstr_create("Un-supported format");
1373 
1374  if (status_type == BBSTATUS_HTML || status_type == BBSTATUS_WML)
1375  para = 1;
1376 
1377  if (!smsc_running) {
1378  if (status_type == BBSTATUS_XML)
1379  return octstr_create ("<smscs>\n\t<count>0</count>\n</smscs>");
1380  else
1381  return octstr_format("%sNo SMSC connections%s\n\n", para ? "<p>" : "",
1382  para ? "</p>" : "");
1383  }
1384 
1385  if (status_type != BBSTATUS_XML)
1386  tmp = octstr_format("%sSMSC connections:%s", para ? "<p>" : "", lb);
1387  else
1388  tmp = octstr_format("<smscs><count>%d</count>\n\t", gwlist_len(smsc_list));
1389 
1390  gw_rwlock_rdlock(&smsc_list_lock);
1391  for (i = 0; i < gwlist_len(smsc_list); i++) {
1392  incoming_sms_load_0 = incoming_sms_load_1 = incoming_sms_load_2 = 0.0;
1393  outgoing_sms_load_0 = outgoing_sms_load_1 = outgoing_sms_load_2 = 0.0;
1394  incoming_dlr_load_0 = incoming_dlr_load_1 = incoming_dlr_load_2 = 0.0;
1395  outgoing_dlr_load_0 = outgoing_dlr_load_1 = outgoing_dlr_load_2 = 0.0;
1396  conn = gwlist_get(smsc_list, i);
1397 
1398  if ((smscconn_info(conn, &info) == -1)) {
1399  /*
1400  * we do not delete SMSCs from the list
1401  * this way we can show in the status which links are dead
1402  */
1403  continue;
1404  }
1405 
1406  conn_id = conn ? smscconn_id(conn) : octstr_imm("unknown");
1407  conn_id = conn_id ? conn_id : octstr_imm("unknown");
1408  conn_admin_id = conn ? smscconn_admin_id(conn) : octstr_imm("unknown");
1409  conn_admin_id = conn_admin_id ? conn_admin_id : octstr_imm("unknown");
1410  conn_name = conn ? smscconn_name(conn) : octstr_imm("unknown");
1411 
1412  if (status_type == BBSTATUS_HTML) {
1413  octstr_append_cstr(tmp, "&nbsp;&nbsp;&nbsp;&nbsp;<b>");
1414  octstr_append(tmp, conn_id);
1415  octstr_append_cstr(tmp, "</b>[");
1416  octstr_append(tmp, conn_admin_id);
1417  octstr_append_cstr(tmp, "]&nbsp;&nbsp;&nbsp;&nbsp;");
1418  } else if (status_type == BBSTATUS_TEXT) {
1419  octstr_append_cstr(tmp, " ");
1420  octstr_append(tmp, conn_id);
1421  octstr_append_cstr(tmp, "[");
1422  octstr_append(tmp, conn_admin_id);
1423  octstr_append_cstr(tmp, "] ");
1424  }
1425  if (status_type == BBSTATUS_XML) {
1426  octstr_append_cstr(tmp, "<smsc>\n\t\t<name>");
1427  octstr_append(tmp, conn_name);
1428  octstr_append_cstr(tmp, "</name>\n\t\t<admin-id>");
1429  octstr_append(tmp, conn_admin_id);
1430  octstr_append_cstr(tmp, "</admin-id>\n\t\t<id>");
1431  octstr_append(tmp, conn_id);
1432  octstr_append_cstr(tmp, "</id>\n\t\t");
1433  } else
1434  octstr_append(tmp, conn_name);
1435 
1436  switch (info.status) {
1437  case SMSCCONN_ACTIVE:
1438  case SMSCCONN_ACTIVE_RECV:
1439  sprintf(tmp3, "online %lds", info.online);
1440  incoming_sms_load_0 = load_get(conn->incoming_sms_load,0);
1441  incoming_sms_load_1 = load_get(conn->incoming_sms_load,1);
1442  incoming_sms_load_2 = load_get(conn->incoming_sms_load,2);
1443  outgoing_sms_load_0 = load_get(conn->outgoing_sms_load,0);
1444  outgoing_sms_load_1 = load_get(conn->outgoing_sms_load,1);
1445  outgoing_sms_load_2 = load_get(conn->outgoing_sms_load,2);
1446  incoming_dlr_load_0 = load_get(conn->incoming_dlr_load,0);
1447  incoming_dlr_load_1 = load_get(conn->incoming_dlr_load,1);
1448  incoming_dlr_load_2 = load_get(conn->incoming_dlr_load,2);
1449  outgoing_dlr_load_0 = load_get(conn->outgoing_dlr_load,0);
1450  outgoing_dlr_load_1 = load_get(conn->outgoing_dlr_load,1);
1451  outgoing_dlr_load_2 = load_get(conn->outgoing_dlr_load,2);
1452  break;
1453  case SMSCCONN_DISCONNECTED:
1454  sprintf(tmp3, "disconnected");
1455  break;
1456  case SMSCCONN_CONNECTING:
1457  sprintf(tmp3, "connecting");
1458  break;
1459  case SMSCCONN_RECONNECTING:
1460  sprintf(tmp3, "re-connecting");
1461  break;
1462  case SMSCCONN_DEAD:
1463  sprintf(tmp3, "dead");
1464  break;
1465  default:
1466  sprintf(tmp3, "unknown");
1467  break;
1468  }
1469 
1470  if (status_type == BBSTATUS_XML)
1471  octstr_format_append(tmp, "<status>%s</status>\n"
1472  "\t\t<failed>%ld</failed>\n"
1473  "\t\t<queued>%ld</queued>\n"
1474  "\t\t<sms>\n"
1475  "\t\t\t<received>%ld</received>\n"
1476  "\t\t\t<sent>%ld</sent>\n"
1477  "\t\t\t<inbound>%.2f,%.2f,%.2f</inbound>\n"
1478  "\t\t\t<outbound>%.2f,%.2f,%.2f</outbound>\n"
1479  "\t\t</sms>\n\t\t<dlr>\n"
1480  "\t\t\t<received>%ld</received>\n"
1481  "\t\t\t<sent>%ld</sent>\n"
1482  "\t\t\t<inbound>%.2f,%.2f,%.2f</inbound>\n"
1483  "\t\t\t<outbound>%.2f,%.2f,%.2f</outbound>\n"
1484  "\t\t</dlr>\n"
1485  "\t</smsc>\n", tmp3,
1486  info.failed, info.queued, info.received, info.sent,
1487  incoming_sms_load_0, incoming_sms_load_1, incoming_sms_load_2,
1488  outgoing_sms_load_0, outgoing_sms_load_1, outgoing_sms_load_2,
1489  info.received_dlr, info.sent_dlr,
1490  incoming_dlr_load_0, incoming_dlr_load_1, incoming_dlr_load_2,
1491  outgoing_dlr_load_0, outgoing_dlr_load_1, outgoing_dlr_load_2);
1492  else
1493  octstr_format_append(tmp, " (%s, rcvd: sms %ld (%.2f,%.2f,%.2f) / dlr %ld (%.2f,%.2f,%.2f), "
1494  "sent: sms %ld (%.2f,%.2f,%.2f) / dlr %ld (%.2f,%.2f,%.2f), failed %ld, "
1495  "queued %ld msgs)%s",
1496  tmp3,
1497  info.received,
1498  incoming_sms_load_0, incoming_sms_load_1, incoming_sms_load_2,
1499  info.received_dlr,
1500  incoming_dlr_load_0, incoming_dlr_load_1, incoming_dlr_load_2,
1501  info.sent,
1502  outgoing_sms_load_0, outgoing_sms_load_1, outgoing_sms_load_2,
1503  info.sent_dlr,
1504  outgoing_dlr_load_0, outgoing_dlr_load_1, outgoing_dlr_load_2,
1505  info.failed,
1506  info.queued,
1507  lb);
1508  }
1509 
1510  gw_rwlock_unlock(&smsc_list_lock);
1511 
1512  if (para)
1513  octstr_append_cstr(tmp, "</p>");
1514  if (status_type == BBSTATUS_XML)
1515  octstr_append_cstr(tmp, "</smscs>\n");
1516  else
1517  octstr_append_cstr(tmp, "\n\n");
1518  return tmp;
1519 }
1520 
1521 
1523 {
1524  CfgGroup *grp;
1525  SMSCConn *conn;
1526  List *keep, *add, *remove;
1527  List *l;
1528  int i, m;
1529 
1530  if (!smsc_running)
1531  return -1;
1532 
1533  gw_rwlock_wrlock(&smsc_list_lock);
1534 
1535  /* load the smsc groups from the config resource */
1536  if (bb_reload_smsc_groups() != 0) {
1537  gw_rwlock_unlock(&smsc_list_lock);
1538  return -1;
1539  }
1540 
1541  /* List of SMSCConn that we keep running */
1542  keep = gwlist_create();
1543 
1544  /* List of CfgGroup that we will add */
1545  add = gwlist_create();
1546 
1547  /* List of SMSCConnn that we will shutdown */
1548  remove = gwlist_create();
1549 
1550  /*
1551  * Loop through the loaded smsc groups
1552  */
1553  for (i = 0; i < gwlist_len(smsc_groups) &&
1554  (grp = gwlist_get(smsc_groups, i)) != NULL; i++) {
1555  /*
1556  * 1st check: Search for the same md5 hash of the whole group.
1557  * If we find it, then this group is already running, and no
1558  * routing information has changed, bail out.
1559  */
1560  if ((l = gwlist_search_all(smsc_list, grp, cmp_conn_grp_checksum)) != NULL) {
1561  while ((conn = gwlist_extract_first(l)) != NULL) {
1562  gwlist_append(keep, conn);
1563  }
1564  gwlist_destroy(l, NULL);
1565  continue;
1566  }
1567  /*
1568  * 2nd check: Search for the same md5 hash minus the routing
1569  * information. If we find it, then this group is already running
1570  * and the routing information changed, we'll apply only the new
1571  * routing information.
1572  */
1573  if ((l = gwlist_search_all(smsc_list, grp, cmp_rout_grp_checksum)) != NULL) {
1574  while ((conn = gwlist_extract_first(l)) != NULL) {
1575  gwlist_append(keep, conn);
1576  smscconn_reconfig(conn, grp);
1577  info(0, "Re-configured routing for smsc-id `%s'.", octstr_get_cstr(conn->id));
1578  }
1579  gwlist_destroy(l, NULL);
1580  continue;
1581  }
1582  /*
1583  * 3rd check: if the smsc-id is NOT in the running list, then
1584  * this is a new group, add it. If the smsc-id IS found, then
1585  * mark it/them to be removed, and add the new group.
1586  */
1587  if ((l = gwlist_search_all(smsc_list, grp, cmp_conn_grp_id)) == NULL) {
1588  gwlist_append(add, grp);
1589  continue;
1590  } else {
1591  while ((conn = gwlist_extract_first(l)) != NULL) {
1592  /* add them to the remove list only
1593  * if they are not yet present inside. */
1594  if (gwlist_search_equal(remove, conn) != -1)
1595  gwlist_append(remove, conn);
1596  }
1597  gwlist_destroy(l, NULL);
1598  gwlist_append(add, grp);
1599  continue;
1600  }
1601  }
1602 
1603  /*
1604  * TODO Effectively a change in the 'instances' multiplier will result in a
1605  * disconnect of all running instances, and re-connecting the number of
1606  * configured instances. The reason for this is that the change in the
1607  * 'instances' value causes the md5 hash to be different for that connection.
1608  * We MAY exclude the 'instances' directive from the while md5 checksum, this
1609  * makes the down-grading easier, allowing the rest to keep running. But the
1610  * up-grading is more difficult, since we can't use the 'add' list here, it
1611  * would create too much instances.
1612  */
1613 
1614  /*
1615  * We may have running smsc-ids now, that haven't been
1616  * re-loaded from the new config, hence add them to be removed.
1617  */
1618  for (i = 0; i < gwlist_len(smsc_list) &&
1619  (conn = gwlist_get(smsc_list, i)) != NULL; i++) {
1620  /* if this is already in the remove list, bail out. */
1621  if (gwlist_search_equal(remove, conn) != -1)
1622  continue;
1623  /* if this is in the keep list, bail out. */
1624  if (gwlist_search_equal(keep, conn) != -1)
1625  continue;
1626  /* mark it to be removed */
1627  gwlist_append(remove, conn);
1628  }
1629  gwlist_destroy(keep, NULL);
1630 
1631  /*
1632  * Stop any connections from the remove list.
1633  *
1634  * The smscconn_shutdown() only initiates the shutdown,
1635  * it is not guaranteed that the SMSC connection is stopped
1636  * and the status is SMSCCONN_DEAD when we return from the
1637  * function call. Therefore we pass the connection to a
1638  * retry list, in order to cleanly destroy all connection
1639  * structures that have been stopped and reached SMSSCONN_DEAD.
1640  */
1641  l = gwlist_create();
1642  gwlist_add_producer(smsc_list);
1643  while ((conn = gwlist_extract_first(remove)) != NULL) {
1644  if ((i = gwlist_search_equal(smsc_list, conn)) != -1) {
1645  gwlist_delete(smsc_list, i, 1);
1646  smscconn_shutdown(conn, 0);
1647  /* if smsc is still in shutdown, then add to retry list */
1648  if (smscconn_destroy(conn) == -1)
1649  gwlist_append(l, conn);
1650  }
1651  }
1652  gwlist_remove_producer(smsc_list);
1653  gwlist_destroy(remove, NULL);
1654 
1655  /*
1656  * Start any connections from the add list.
1657  */
1658  gwlist_add_producer(smsc_list);
1659  while ((grp = gwlist_extract_first(add)) != NULL) {
1660  /* multiple instances for the same group? */
1661  m = smscconn_instances(grp);
1662  for (i = 0; i < m; i++) {
1663  conn = smscconn_create(grp, 1);
1664  if (conn != NULL) {
1665  gwlist_append(smsc_list, conn);
1666  if (conn->dead_start) {
1667  /* Shutdown connection if it's not configured to connect at start-up time */
1668  smscconn_shutdown(conn, 0);
1669  } else {
1670  smscconn_start(conn);
1671  }
1672  }
1673  }
1674  }
1675  gwlist_remove_producer(smsc_list);
1676  gwlist_destroy(add, NULL);
1677 
1678  gw_rwlock_unlock(&smsc_list_lock);
1679 
1680  /* wake-up the router */
1681  if (router_thread >= 0)
1683 
1684  /*
1685  * We may still have pending connections in the retry list
1686  * that haven't been destroyed yet.
1687  */
1688  while ((conn = gwlist_extract_first(l)) != NULL) {
1689  if (smscconn_destroy(conn) == -1) {
1690  gwlist_append(l, conn);
1691  gwthread_sleep(2);
1692  }
1693  }
1694  gwlist_destroy(l, NULL);
1695 
1696  return 0;
1697 }
1698 
1699 
1700 /* function to route outgoing SMS'es
1701  *
1702  * If finds a good one, puts into it and returns SMSCCONN_SUCCESS
1703  * If finds only bad ones, but acceptable, queues and
1704  * returns SMSCCONN_QUEUED (like all acceptable currently disconnected)
1705  * if message acceptable but queues full returns SMSCCONN_FAILED_QFULL and
1706  * message is not destroyed.
1707  * If cannot find nothing at all, returns SMSCCONN_FAILED_DISCARDED and
1708  * message is NOT destroyed (otherwise it is)
1709  */
1710 long smsc2_rout(Msg *msg, int resend)
1711 {
1712  StatusInfo stat;
1713  SMSCConn *conn, *best_preferred, *best_ok;
1714  long bp_load, bo_load;
1715  int i, s, ret, bad_found, full_found;
1716  long max_queue, queue_length;
1717  char *uf;
1718 
1719  /* XXX handle ack here? */
1720  if (msg_type(msg) != sms) {
1721  error(0, "Attempt to route non SMS message through smsc2_rout!");
1723  }
1724 
1725  /* check if validity period has expired */
1726  if (msg->sms.validity != SMS_PARAM_UNDEFINED && time(NULL) > msg->sms.validity) {
1728  return SMSCCONN_FAILED_EXPIRED;
1729  }
1730 
1731  /* unify prefix of receiver, in case of it has not been
1732  * already done */
1733  uf = unified_prefix ? octstr_get_cstr(unified_prefix) : NULL;
1734  normalize_number(uf, &(msg->sms.receiver));
1735 
1736  /* check for white/back-listed sender/receiver */
1737  gw_rwlock_rdlock(&white_black_list_lock);
1738  if (white_list_sender && numhash_find_number(white_list_sender, msg->sms.sender) < 1) {
1739  gw_rwlock_unlock(&white_black_list_lock);
1740  info(0, "Number <%s> is not in white-list, message rejected",
1741  octstr_get_cstr(msg->sms.sender));
1742  bb_smscconn_send_failed(NULL, msg_duplicate(msg), SMSCCONN_FAILED_REJECTED, octstr_create("sender not in white-list"));
1743  return SMSCCONN_FAILED_REJECTED;
1744  }
1745 
1746  if (white_list_sender_regex && gw_regex_match_pre(white_list_sender_regex, msg->sms.sender) == 0) {
1747  gw_rwlock_unlock(&white_black_list_lock);
1748  info(0, "Number <%s> is not in white-list, message rejected",
1749  octstr_get_cstr(msg->sms.sender));
1750  bb_smscconn_send_failed(NULL, msg_duplicate(msg), SMSCCONN_FAILED_REJECTED, octstr_create("sender not in white-list"));
1751  return SMSCCONN_FAILED_REJECTED;
1752  }
1753 
1754  if (black_list_sender && numhash_find_number(black_list_sender, msg->sms.sender) == 1) {
1755  gw_rwlock_unlock(&white_black_list_lock);
1756  info(0, "Number <%s> is in black-list, message rejected",
1757  octstr_get_cstr(msg->sms.sender));
1758  bb_smscconn_send_failed(NULL, msg_duplicate(msg), SMSCCONN_FAILED_REJECTED, octstr_create("sender in black-list"));
1759  return SMSCCONN_FAILED_REJECTED;
1760  }
1761 
1762  if (black_list_sender_regex && gw_regex_match_pre(black_list_sender_regex, msg->sms.sender) == 0) {
1763  gw_rwlock_unlock(&white_black_list_lock);
1764  info(0, "Number <%s> is not in black-list, message rejected",
1765  octstr_get_cstr(msg->sms.sender));
1766  bb_smscconn_send_failed(NULL, msg_duplicate(msg), SMSCCONN_FAILED_REJECTED, octstr_create("sender in black-list"));
1767  return SMSCCONN_FAILED_REJECTED;
1768  }
1769 
1770  if (white_list_receiver && numhash_find_number(white_list_receiver, msg->sms.receiver) < 1) {
1771  gw_rwlock_unlock(&white_black_list_lock);
1772  info(0, "Number <%s> is not in white-list-receiver, message rejected",
1773  octstr_get_cstr(msg->sms.receiver));
1774  bb_smscconn_send_failed(NULL, msg_duplicate(msg), SMSCCONN_FAILED_REJECTED, octstr_create("receiver not in white-list"));
1775  return SMSCCONN_FAILED_REJECTED;
1776  }
1777 
1778  if (white_list_receiver_regex && gw_regex_match_pre(white_list_receiver_regex, msg->sms.receiver) == 0) {
1779  gw_rwlock_unlock(&white_black_list_lock);
1780  info(0, "Number <%s> is not in white-list-receiver, message rejected",
1781  octstr_get_cstr(msg->sms.receiver));
1782  bb_smscconn_send_failed(NULL, msg_duplicate(msg), SMSCCONN_FAILED_REJECTED, octstr_create("receiver not in white-list"));
1783  return SMSCCONN_FAILED_REJECTED;
1784  }
1785 
1786  if (black_list_receiver && numhash_find_number(black_list_receiver, msg->sms.receiver) == 1) {
1787  gw_rwlock_unlock(&white_black_list_lock);
1788  info(0, "Number <%s> is in black-list-receiver, message rejected",
1789  octstr_get_cstr(msg->sms.receiver));
1790  bb_smscconn_send_failed(NULL, msg_duplicate(msg), SMSCCONN_FAILED_REJECTED, octstr_create("receiver in black-list"));
1791  return SMSCCONN_FAILED_REJECTED;
1792  }
1793 
1794  if (black_list_receiver_regex && gw_regex_match_pre(black_list_receiver_regex, msg->sms.receiver) == 0) {
1795  gw_rwlock_unlock(&white_black_list_lock);
1796  info(0, "Number <%s> is not in black-list-receiver, message rejected",
1797  octstr_get_cstr(msg->sms.receiver));
1798  bb_smscconn_send_failed(NULL, msg_duplicate(msg), SMSCCONN_FAILED_REJECTED, octstr_create("receiver in black-list"));
1799  return SMSCCONN_FAILED_REJECTED;
1800  }
1801  gw_rwlock_unlock(&white_black_list_lock);
1802 
1803  /* select in which list to add this
1804  * start - from random SMSCConn, as they are all 'equal'
1805  */
1806  gw_rwlock_rdlock(&smsc_list_lock);
1807  if (gwlist_len(smsc_list) == 0) {
1808  warning(0, "No SMSCes to receive message");
1809  gw_rwlock_unlock(&smsc_list_lock);
1811  }
1812 
1813  best_preferred = best_ok = NULL;
1814  bad_found = full_found = 0;
1815  bp_load = bo_load = queue_length = 0;
1816 
1817  if (msg->sms.split_parts == NULL) {
1818  /*
1819  * if global queue not empty then 20% reserved for old msgs
1820  * and 80% for new msgs. So we can guarantee that old msgs find
1821  * place in the SMSC's queue.
1822  */
1823  if (gwlist_len(outgoing_sms) > 0) {
1824  max_queue = (resend ? max_outgoing_sms_qlength :
1825  max_outgoing_sms_qlength * 0.8);
1826  } else
1827  max_queue = max_outgoing_sms_qlength;
1828 
1829  s = gw_rand() % gwlist_len(smsc_list);
1830 
1831  conn = NULL;
1832  for (i = 0; i < gwlist_len(smsc_list); i++) {
1833  conn = gwlist_get(smsc_list, (i+s) % gwlist_len(smsc_list));
1834 
1835  smscconn_info(conn, &stat);
1836  queue_length += (stat.queued > 0 ? stat.queued : 0);
1837 
1838  ret = smscconn_usable(conn,msg);
1839  if (ret == -1)
1840  continue;
1841 
1842  /* if we already have a preferred one, skip non-preferred */
1843  if (ret != 1 && best_preferred)
1844  continue;
1845 
1846  /* If connection is not currently answering ... */
1847  if (stat.status != SMSCCONN_ACTIVE) {
1848  bad_found = 1;
1849  continue;
1850  }
1851  /* check queue length */
1852  if (stat.queued > max_queue) {
1853  full_found = 1;
1854  continue;
1855  }
1856  if (ret == 1) { /* preferred */
1857  if (best_preferred == NULL || stat.load < bp_load) {
1858  best_preferred = conn;
1859  bp_load = stat.load;
1860  continue;
1861  }
1862  }
1863  if (best_ok == NULL || stat.load < bo_load) {
1864  best_ok = conn;
1865  bo_load = stat.load;
1866  }
1867  }
1868  queue_length += gwlist_len(outgoing_sms);
1869  if (max_outgoing_sms_qlength > 0 && !resend &&
1870  queue_length > gwlist_len(smsc_list) * max_outgoing_sms_qlength) {
1871  gw_rwlock_unlock(&smsc_list_lock);
1872  debug("bb.sms", 0, "sum(#queues) limit");
1873  return SMSCCONN_FAILED_QFULL;
1874  }
1875  } else {
1876  struct split_parts *parts = msg->sms.split_parts;
1877  /* check whether this SMSCConn still on the list */
1878  if (gwlist_search_equal(smsc_list, parts->smsc_conn) != -1)
1879  best_preferred = parts->smsc_conn;
1880  }
1881 
1882  if (best_preferred)
1883  ret = smscconn_send(best_preferred, msg);
1884  else if (best_ok)
1885  ret = smscconn_send(best_ok, msg);
1886  else if (bad_found) {
1887  gw_rwlock_unlock(&smsc_list_lock);
1888  if (max_outgoing_sms_qlength < 0 || gwlist_len(outgoing_sms) < max_outgoing_sms_qlength) {
1889  gwlist_produce(outgoing_sms, msg);
1890  return SMSCCONN_QUEUED;
1891  }
1892  debug("bb.sms", 0, "bad_found queue full");
1893  return SMSCCONN_FAILED_QFULL; /* queue full */
1894  } else if (full_found) {
1895  gw_rwlock_unlock(&smsc_list_lock);
1896  debug("bb.sms", 0, "full_found queue full");
1897  return SMSCCONN_FAILED_QFULL;
1898  } else {
1899  gw_rwlock_unlock(&smsc_list_lock);
1900  if (bb_status == BB_SHUTDOWN) {
1901  msg_destroy(msg);
1902  return SMSCCONN_QUEUED;
1903  }
1904  warning(0, "Cannot find SMSCConn for message to <%s>, rejected.",
1905  octstr_get_cstr(msg->sms.receiver));
1908  }
1909 
1910  gw_rwlock_unlock(&smsc_list_lock);
1911  /* check the status of sending operation */
1912  if (ret == -1)
1913  return smsc2_rout(msg, resend); /* re-try */
1914 
1915  msg_destroy(msg);
1916  return SMSCCONN_SUCCESS;
1917 }
1918 
1919 
1920 /*
1921  * Try to reroute to another smsc.
1922  * @return -1 if no rerouting info available; otherwise return code from smsc2_route.
1923  */
1925 {
1926  Octstr *smsc;
1927 
1928  /* sanity check */
1929  if (!conn || !msg)
1930  return -1;
1931 
1932  /* check for dlr rerouting */
1933  if (!conn->reroute_dlr && (msg->sms.sms_type == report_mo || msg->sms.sms_type == report_mt))
1934  return -1;
1935 
1936  /*
1937  * Check if we have any "reroute" rules to obey. Which means msg gets
1938  * transported internally from MO to MT msg.
1939  */
1940  if (conn->reroute) {
1941  /* change message direction */
1943  msg->sms.sms_type = mt_push;
1944  store_save(msg);
1945  /* drop into outbound queue again for routing */
1946  return smsc2_rout(msg, 0);
1947  }
1948 
1949  if (conn->reroute_to_smsc) {
1950  /* change message direction */
1952  msg->sms.sms_type = mt_push;
1953  store_save(msg);
1954  /* apply directly to the given smsc-id for MT traffic */
1955  octstr_destroy(msg->sms.smsc_id);
1956  msg->sms.smsc_id = octstr_duplicate(conn->reroute_to_smsc);
1957  return smsc2_rout(msg, 0);
1958  }
1959 
1960  if (conn->reroute_by_receiver && msg->sms.receiver &&
1961  (smsc = dict_get(conn->reroute_by_receiver, msg->sms.receiver))) {
1962  /* change message direction */
1964  msg->sms.sms_type = mt_push;
1965  store_save(msg);
1966  /* route by receiver number */
1967  /* XXX implement wildcard matching too! */
1968  octstr_destroy(msg->sms.smsc_id);
1969  msg->sms.smsc_id = octstr_duplicate(smsc);
1970  return smsc2_rout(msg, 0);
1971  }
1972 
1973  return -1;
1974 }
1975 
1976 
1977 /*--------------------------------
1978  * incoming concatenated messages handling
1979  */
1980 
1981 typedef struct ConcatMsg {
1982  int refnum;
1985  Octstr *udh; /* normalized UDH */
1986  time_t trecv;
1987  Octstr *key; /* in dict. */
1988  int ack; /* set to the type of ack to send when deleting. */
1989  /* array of parts */
1991  Octstr *smsc_id; /* name of smsc conn where we received this msgs */
1992 } ConcatMsg;
1993 
1996 
1997 static void destroy_concatMsg(void *x)
1998 {
1999  int i;
2000  ConcatMsg *msg = x;
2001 
2002  gw_assert(msg);
2003  for (i = 0; i < msg->total_parts; i++) {
2004  if (msg->parts[i]) {
2005  store_save_ack(msg->parts[i], msg->ack);
2006  msg_destroy(msg->parts[i]);
2007  }
2008  }
2009  gw_free(msg->parts);
2010  octstr_destroy(msg->key);
2011  octstr_destroy(msg->udh);
2012  octstr_destroy(msg->smsc_id);
2013  gw_free(msg);
2014 }
2015 
2016 static void concat_handling_init(void)
2017 {
2018  if (incoming_concat_msgs != NULL) /* already initialised? */
2019  return;
2020  incoming_concat_msgs = dict_create(max_incoming_sms_qlength > 0 ? max_incoming_sms_qlength : 1024,
2022  concat_lock = mutex_create();
2023  debug("bb.sms",0,"MO concatenated message handling enabled");
2024 }
2025 
2026 static void concat_handling_shutdown(void)
2027 {
2028  /* check if we were enabled at all? */
2030  return;
2031 
2032  /* deactivate */
2034 
2035  /* go through the queue and send messages as is */
2037 }
2038 
2039 static void concat_handling_cleanup(void)
2040 {
2041  if (incoming_concat_msgs == NULL)
2042  return;
2043  dict_destroy(incoming_concat_msgs);
2044  mutex_destroy(concat_lock);
2045 
2046  incoming_concat_msgs = NULL;
2047  concat_lock = NULL;
2048  debug("bb.sms",0,"MO concatenated message handling cleaned up");
2049 }
2050 
2051 static void concat_handling_clear_old_parts(int force)
2052 {
2053  List *keys;
2054  Octstr *key;
2055 
2056  /* not initialized, go away */
2057  if (incoming_concat_msgs == NULL)
2058  return;
2059 
2060  debug("bb.sms.splits", 0, "clear_old_concat_parts called");
2061 
2062  /* Remove any pending messages that are too old. */
2063  keys = dict_keys(incoming_concat_msgs);
2064  while((key = gwlist_extract_first(keys)) != NULL) {
2065  ConcatMsg *x;
2066  Msg *msg;
2067  SMSCConn *conn;
2068  int i, destroy = 1, smsc_index;
2069 
2070  mutex_lock(concat_lock);
2071  x = dict_get(incoming_concat_msgs, key);
2072  octstr_destroy(key);
2073  if (x == NULL || (!force && difftime(time(NULL), x->trecv) < concatenated_mo_timeout)) {
2074  mutex_unlock(concat_lock);
2075  continue;
2076  }
2077  dict_remove(incoming_concat_msgs, x->key);
2078  mutex_unlock(concat_lock);
2079 
2080  /* try to find SMSCConn */
2081  gw_rwlock_rdlock(&smsc_list_lock);
2085  smsc_index = smsc2_find(x->smsc_id, 0);
2086  if (smsc_index != -1) {
2087  conn = gwlist_get(smsc_list, smsc_index);
2088  warning(0, "Time-out waiting for concatenated message '%s'. Send message parts as is.",
2089  octstr_get_cstr(x->key));
2090  for (i = 0; i < x->total_parts && destroy == 1; i++) {
2091  if (x->parts[i] == NULL)
2092  continue;
2093  msg = msg_duplicate(x->parts[i]);
2094  switch(bb_smscconn_receive_internal(conn, msg)) {
2096  case SMSCCONN_QUEUED:
2097  case SMSCCONN_SUCCESS:
2098  msg_destroy(x->parts[i]);
2099  x->parts[i] = NULL;
2100  x->num_parts--;
2101  break;
2103  case SMSCCONN_FAILED_QFULL:
2104  default:
2105  /* oops put it back into dict and retry on next run */
2106  store_save(x->parts[i]);
2107  destroy = 0;
2108  break;
2109  }
2110  }
2111  }
2112  gw_rwlock_unlock(&smsc_list_lock);
2113 
2114  if (destroy) {
2115  destroy_concatMsg(x);
2116  } else {
2117  ConcatMsg *x1;
2118  mutex_lock(concat_lock);
2119  x1 = dict_get(incoming_concat_msgs, x->key);
2120  if (x1 != NULL) { /* oops we have new part */
2121  int i;
2122  if (x->total_parts != x1->total_parts) {
2123  /* broken handset, don't know what todo here??
2124  * for now just put old concatMsg into dict with
2125  * another key and it will be cleaned up on next run.
2126  */
2127  octstr_format_append(x->key, " %d", x->total_parts);
2128  dict_put(incoming_concat_msgs, x->key, x);
2129  } else {
2130  for (i = 0; i < x->total_parts; i++) {
2131  if (x->parts[i] == NULL)
2132  continue;
2133  if (x1->parts[i] == NULL) {
2134  x1->parts[i] = x->parts[i];
2135  x->parts[i] = NULL;
2136  }
2137  }
2138  destroy_concatMsg(x);
2139  }
2140  } else {
2141  dict_put(incoming_concat_msgs, x->key, x);
2142  }
2143  mutex_unlock(concat_lock);
2144  }
2145  }
2147 }
2148 
2149 /* Checks if message is concatenated. Returns:
2150  * - returns concat_complete if no concat parts, or message complete
2151  * - returns concat_pending (and sets *pmsg to NULL) if parts pending
2152  * - returns concat_error if store_save fails
2153  */
2154 static int concat_handling_check_and_handle(Msg **pmsg, Octstr *smscid)
2155 {
2156  Msg *msg = *pmsg;
2157  int l, iel = 0, refnum, pos, c, part, totalparts, i, sixteenbit;
2158  Octstr *udh = msg->sms.udhdata, *key;
2159  ConcatMsg *cmsg;
2160  int ret = concat_complete;
2161 
2163  return concat_none;
2164 
2165  /* ... module not initialised or there is no UDH or smscid is NULL. */
2166  if (incoming_concat_msgs == NULL || (l = octstr_len(udh)) == 0 || smscid == NULL)
2167  return concat_none;
2168 
2169  for (pos = 1, c = -1; pos < l - 1; pos += iel + 2) {
2170  iel = octstr_get_char(udh, pos + 1);
2171  if ((c = octstr_get_char(udh, pos)) == 0 || c == 8)
2172  break;
2173  }
2174  if (pos >= l) /* no concat UDH found. */
2175  return concat_none;
2176 
2177  /* c = 0 means 8 bit, c = 8 means 16 bit concat info */
2178  sixteenbit = (c == 8);
2179  refnum = (!sixteenbit) ? octstr_get_char(udh, pos + 2) :
2180  (octstr_get_char(udh, pos + 2) << 8) | octstr_get_char(udh, pos + 3);
2181  totalparts = octstr_get_char(udh, pos + 3 + sixteenbit);
2182  part = octstr_get_char(udh, pos + 4 + sixteenbit);
2183 
2184  if (part < 1 || part > totalparts) {
2185  warning(0, "Invalid concatenation UDH [ref = %d] in message from %s!",
2186  refnum, octstr_get_cstr(msg->sms.sender));
2187  return concat_none;
2188  }
2189 
2190  /* extract UDH */
2191  udh = octstr_duplicate(msg->sms.udhdata);
2192  octstr_delete(udh, pos, iel + 2);
2193  if (octstr_len(udh) <= 1) /* no other UDH elements. */
2194  octstr_delete(udh, 0, octstr_len(udh));
2195  else
2196  octstr_set_char(udh, 0, octstr_len(udh) - 1);
2197 
2198  debug("bb.sms.splits", 0, "Got part %d [ref %d, total parts %d] of message from %s. Dump follows:",
2199  part, refnum, totalparts, octstr_get_cstr(msg->sms.sender));
2200 
2201  msg_dump(msg, 0);
2202 
2203  key = octstr_format("'%S' '%S' '%S' '%d' '%d' '%H'", msg->sms.sender, msg->sms.receiver, smscid, refnum, totalparts, udh);
2204  mutex_lock(concat_lock);
2205  if ((cmsg = dict_get(incoming_concat_msgs, key)) == NULL) {
2206  cmsg = gw_malloc(sizeof(*cmsg));
2207  cmsg->refnum = refnum;
2208  cmsg->total_parts = totalparts;
2209  cmsg->udh = udh;
2210  udh = NULL;
2211  cmsg->num_parts = 0;
2212  cmsg->key = octstr_duplicate(key);
2213  cmsg->ack = ack_success;
2214  cmsg->smsc_id = octstr_duplicate(smscid);
2215  cmsg->parts = gw_malloc(totalparts * sizeof(*cmsg->parts));
2216  memset(cmsg->parts, 0, cmsg->total_parts * sizeof(*cmsg->parts)); /* clear it. */
2217 
2218  dict_put(incoming_concat_msgs, key, cmsg);
2219  }
2220  octstr_destroy(key);
2221  octstr_destroy(udh);
2222 
2223  /* check if we have seen message part before... */
2224  if (cmsg->parts[part - 1] != NULL) {
2225  error(0, "Duplicate message part %d, ref %d, from %s, to %s. Discarded!",
2226  part, refnum, octstr_get_cstr(msg->sms.sender), octstr_get_cstr(msg->sms.receiver));
2228  msg_destroy(msg);
2229  *pmsg = msg = NULL;
2230  mutex_unlock(concat_lock);
2231  return concat_pending;
2232  } else {
2233  cmsg->parts[part -1] = msg;
2234  cmsg->num_parts++;
2235  /* always update receive time so we have it from last part and don't timeout */
2236  cmsg->trecv = time(NULL);
2237  }
2238 
2239  if (cmsg->num_parts < cmsg->total_parts) { /* wait for more parts. */
2240  *pmsg = msg = NULL;
2241  mutex_unlock(concat_lock);
2242  return concat_pending;
2243  }
2244 
2245  /* we have all the parts: Put them together, modify UDH, return message. */
2246  msg = msg_duplicate(cmsg->parts[0]);
2247  uuid_generate(msg->sms.id); /* give it a new ID. */
2248 
2249  debug("bb.sms.splits",0,"Received all concatenated message parts from %s, to %s, refnum %d",
2250  octstr_get_cstr(msg->sms.sender), octstr_get_cstr(msg->sms.receiver), refnum);
2251 
2252  for (i = 1; i < cmsg->total_parts; i++)
2253  octstr_append(msg->sms.msgdata, cmsg->parts[i]->sms.msgdata);
2254 
2255  /* Attempt to save the new one, if that fails, then reply with fail. */
2256  if (store_save(msg) == -1) {
2257  mutex_unlock(concat_lock);
2258  msg_destroy(msg);
2259  *pmsg = msg = NULL;
2260  return concat_error;
2261  } else
2262  *pmsg = msg; /* return the message part. */
2263 
2264  /* fix up UDH */
2265  octstr_destroy(msg->sms.udhdata);
2266  msg->sms.udhdata = cmsg->udh;
2267  cmsg->udh = NULL;
2268 
2269  /* Delete it from the queue and from the Dict. */
2270  /* Note: dict_put with NULL value delete and destroy value */
2271  dict_put(incoming_concat_msgs, cmsg->key, NULL);
2272  mutex_unlock(concat_lock);
2273 
2274  debug("bb.sms.splits", 0, "Got full message [ref %d] of message from %s to %s. Dumping: ",
2275  refnum, octstr_get_cstr(msg->sms.sender), octstr_get_cstr(msg->sms.receiver));
2276  msg_dump(msg,0);
2277 
2278  return ret;
2279 }
2280 
Load * incoming_sms_load
Definition: smscconn_p.h:215
Dict * dict_create(long size_hint, void(*destroy_value)(void *))
Definition: dict.c:192
Octstr * name
Definition: smscconn_p.h:173
void msg_dump(Msg *msg, int level)
Definition: msg.c:152
long online
Definition: smscconn.h:122
void error(int err, const char *fmt,...)
Definition: log.c:612
void bb_alog_sms(SMSCConn *conn, Msg *msg, const char *message)
Definition: bb_alog.c:374
void info(int err, const char *fmt,...)
Definition: log.c:636
Counter * parts_left
Definition: msg.h:94
Msg * msg_duplicate(Msg *msg)
Definition: msg.c:111
void bb_smscconn_connected(SMSCConn *conn)
Definition: bb_smscconn.c:192
Load * outgoing_dlr_load
Definition: bearerbox.c:105
static Cfg * cfg_reloaded
Definition: bb_smscconn.c:130
unsigned long received_dlr
Definition: smscconn.h:117
int smsc2_add_smsc(Octstr *id)
Definition: bb_smscconn.c:1112
Counter * outgoing_sms_counter
Definition: bearerbox.c:91
static long concatenated_mo_timeout
Definition: bb_smscconn.c:164
long gwlist_search_equal(List *list, void *item)
Definition: list.c:534
static List * smsc_groups
Definition: bb_smscconn.c:131
Octstr * key
Definition: bb_smscconn.c:1987
void smsc2_cleanup(void)
Definition: bb_smscconn.c:1306
void bb_smscconn_ready(SMSCConn *conn)
Definition: bb_smscconn.c:185
static long router_thread
Definition: bb_smscconn.c:149
int smscconn_destroy(SMSCConn *conn)
Definition: smscconn.c:406
Counter * incoming_sms_counter
Definition: bearerbox.c:90
Definition: msg.h:106
void dict_put(Dict *dict, Octstr *key, void *value)
Definition: dict.c:240
void counter_destroy(Counter *counter)
Definition: counter.c:110
#define mutex_unlock(m)
Definition: thread.h:136
void gwlist_append(List *list, void *item)
Definition: list.c:179
int dead_start
Definition: smscconn_p.h:210
static regex_t * white_list_sender_regex
Definition: bb_smscconn.c:144
int smsc2_restart_smsc(Octstr *id)
Definition: bb_smscconn.c:998
char * bb_status_linebreak(int status_type)
Definition: bearerbox.c:1097
void smscconn_shutdown(SMSCConn *conn, int finish_sending)
Definition: smscconn.c:378
void bb_smscconn_killed(void)
Definition: bb_smscconn.c:199
List * flow_threads
Definition: bearerbox.c:116
void octstr_append(Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:1502
static Mutex * concat_lock
Definition: bb_smscconn.c:1995
Definition: msg.h:109
void gwlist_produce(List *list, void *item)
Definition: list.c:411
static RWLock smsc_list_lock
Definition: bb_smscconn.c:129
Octstr * id
Definition: smscconn_p.h:174
long gwlist_len(List *list)
Definition: list.c:166
int(* store_save_ack)(Msg *msg, ack_status_t status)
Definition: bb_store.c:73
static long route_incoming_to_smsc(SMSCConn *conn, Msg *msg)
Definition: bb_smscconn.c:1924
void gw_rwlock_destroy(RWLock *lock)
Definition: gw-rwlock.c:112
Counter * failed
Definition: smscconn_p.h:166
int gw_rwlock_wrlock(RWLock *lock)
Definition: gw-rwlock.c:177
int smsc2_reload_lists(void)
Definition: bb_smscconn.c:1166
#define mutex_create()
Definition: thread.h:96
void * gwlist_get(List *list, long pos)
Definition: list.c:292
msg_type
Definition: msg.h:73
Octstr * cfg_get_group_checksum(CfgGroup *grp,...)
Definition: cfg.c:663
Msg * create_dlr_from_msg(const Octstr *smsc, const Msg *msg, const Octstr *reply, long stat)
Definition: dlr.c:501
#define cfg_get(grp, varname)
Definition: cfg.h:86
const Octstr * smscconn_name(SMSCConn *conn)
Definition: smscconn.c:493
static regex_t * black_list_receiver_regex
Definition: bb_smscconn.c:147
void uuid_generate(uuid_t out)
Definition: gw_uuid.c:392
#define DLR_IS_FAIL(dlr)
Definition: dlr.h:87
List * outgoing_sms
Definition: bearerbox.c:85
static long sms_resend_retry
Definition: bb_smscconn.c:153
Octstr * smsc_id
Definition: bb_smscconn.c:1991
long max_outgoing_sms_qlength
Definition: bearerbox.c:99
Dict * reroute_by_receiver
Definition: smscconn_p.h:207
unsigned long counter_decrease(Counter *counter)
Definition: counter.c:155
int gw_rwlock_rdlock(RWLock *lock)
Definition: gw-rwlock.c:134
smscconn_status_t status
Definition: smscconn.h:113
static int cmp_conn_grp_id(void *a, void *b)
Definition: bb_smscconn.c:788
void numhash_destroy(Numhash *table)
Definition: numhash.c:275
void octstr_append_cstr(Octstr *ostr, const char *cstr)
Definition: octstr.c:1509
Definition: msg.h:110
void octstr_insert_data(Octstr *ostr, long pos, const char *data, long len)
Definition: octstr.c:1459
double load_get(Load *load, int pos)
Definition: load.c:191
static long bb_smscconn_receive_internal(SMSCConn *conn, Msg *sms)
Definition: bb_smscconn.c:417
static void concat_handling_clear_old_parts(int force)
Definition: bb_smscconn.c:2051
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
List * incoming_sms
Definition: bearerbox.c:84
static RWLock white_black_list_lock
Definition: bb_smscconn.c:134
Load * incoming_sms_load
Definition: bearerbox.c:103
unsigned long counter_increase(Counter *counter)
Definition: counter.c:123
unsigned int smscconn_instances(CfgGroup *grp)
Definition: smscconn.c:149
Counter * incoming_dlr_counter
Definition: bearerbox.c:92
Cfg * cfg_create(Octstr *filename)
Definition: cfg.c:318
unsigned long sent_dlr
Definition: smscconn.h:119
Numhash * numhash_create(const char *seek_url)
Definition: numhash.c:313
long queued
Definition: smscconn.h:121
static Numhash * white_list_sender
Definition: bb_smscconn.c:140
int cfg_read(Cfg *cfg)
Definition: cfg.c:452
Load * outgoing_sms_load
Definition: smscconn_p.h:214
const Octstr * smscconn_admin_id(SMSCConn *conn)
Definition: smscconn.c:507
List * gwlist_search_all(List *list, void *pattern, int(*cmp)(void *, void *))
Definition: list.c:508
Counter * outgoing_dlr_counter
Definition: bearerbox.c:93
long status
Definition: msg.h:96
int smsc2_remove_smsc(Octstr *id)
Definition: bb_smscconn.c:1083
static Octstr * black_list_receiver_url
Definition: bb_smscconn.c:137
int smpp_pdu_shutdown(void)
Definition: smpp_pdu.c:261
#define DLR_IS_SMSC_FAIL(dlr)
Definition: dlr.h:90
void smscconn_reconfig(SMSCConn *conn, CfgGroup *grp)
Definition: smscconn.c:704
Definition: msg.h:108
Load * incoming_dlr_load
Definition: bearerbox.c:104
Counter * sent
Definition: smscconn_p.h:164
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:281
Counter * received_dlr
Definition: smscconn_p.h:163
Definition: msg.h:79
Definition: cfg.c:164
int smscconn_status(SMSCConn *conn)
Definition: smscconn.c:665
void * dict_remove(Dict *dict, Octstr *key)
Definition: dict.c:307
int numhash_find_number(Numhash *table, Octstr *nro)
Definition: numhash.c:218
Counter * counter_create(void)
Definition: counter.c:94
Octstr * reroute_to_smsc
Definition: smscconn_p.h:208
void cfg_destroy(Cfg *cfg)
Definition: cfg.c:331
unsigned long sent
Definition: smscconn.h:118
int smsc2_stop_smsc(Octstr *id)
Definition: bb_smscconn.c:968
void * gwlist_extract_first(List *list)
Definition: list.c:305
Octstr * chksum_conn
Definition: smscconn_p.h:172
Octstr * cfg_filename
Definition: bearerbox.c:130
static Dict * incoming_concat_msgs
Definition: bb_smscconn.c:1994
void gwlist_delete(List *list, long pos, long count)
Definition: list.c:232
static Numhash * black_list_sender
Definition: bb_smscconn.c:139
Octstr * admin_id
Definition: smscconn_p.h:176
void * dict_get(Dict *dict, Octstr *key)
Definition: dict.c:286
time_t trecv
Definition: bb_smscconn.c:1986
void octstr_delete(Octstr *ostr1, long pos, long len)
Definition: octstr.c:1525
void gwlist_remove_producer(List *list)
Definition: list.c:401
Octstr * unified_prefix
Definition: smscconn_p.h:190
#define OCTSTR(os)
Definition: bb_smscconn.c:733
int bb_reload_smsc_groups()
Definition: bb_smscconn.c:628
Octstr * chksum
Definition: smscconn_p.h:171
static int cmp_conn_grp_checksum(void *a, void *b)
Definition: bb_smscconn.c:735
long max_incoming_sms_qlength
Definition: bearerbox.c:98
long bb_smscconn_receive(SMSCConn *conn, Msg *sms)
Definition: bb_smscconn.c:478
int smscconn_stop(SMSCConn *conn)
Definition: smscconn.c:457
static void concat_handling_init(void)
Definition: bb_smscconn.c:2016
unsigned long failed
Definition: smscconn.h:120
int reroute
Definition: smscconn_p.h:206
int route_incoming_to_boxc(Msg *msg)
Definition: bb_boxc.c:1511
const Octstr * smscconn_id(SMSCConn *conn)
Definition: smscconn.c:500
Definition: dict.c:116
#define octstr_duplicate(ostr)
Definition: octstr.h:187
List * cfg_get_multi_group(Cfg *cfg, Octstr *name)
Definition: cfg.c:642
static void concat_handling_cleanup(void)
Definition: bb_smscconn.c:2039
static void sms_router(void *arg)
Definition: bb_smscconn.c:651
void msg_destroy(Msg *msg)
Definition: msg.c:132
int gw_rwlock_unlock(RWLock *lock)
Definition: gw-rwlock.c:155
Counter * split_msg_counter
Definition: bb_smscconn.c:159
void warning(int err, const char *fmt,...)
Definition: log.c:624
Octstr * udh
Definition: bb_smscconn.c:1985
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2462
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
#define gwthread_create(func, arg)
Definition: gwthread.h:90
#define octstr_create(cstr)
Definition: octstr.h:125
void octstr_destroy_item(void *os)
Definition: octstr.c:334
#define DLR_SMSC_FAIL
Definition: dlr.h:76
gw_assert(wtls_machine->packet_to_send!=NULL)
#define DLR_IS_SMSC_SUCCESS(dlr)
Definition: dlr.h:89
void gwthread_sleep(double seconds)
void mutex_destroy(Mutex *mutex)
Definition: thread.c:97
static regex_t * white_list_receiver_regex
Definition: bb_smscconn.c:146
#define SMS_PARAM_UNDEFINED
Definition: sms.h:91
void smsc2_suspend(void)
Definition: bb_smscconn.c:1251
int load
Definition: smscconn.h:123
static Octstr * white_list_sender_url
Definition: bb_smscconn.c:136
static void handle_split(SMSCConn *conn, Msg *msg, long reason)
Definition: bb_smscconn.c:209
int smscconn_send(SMSCConn *conn, Msg *msg)
Definition: smscconn.c:596
void * smsc_conn
Definition: msg.h:98
Load * outgoing_sms_load
Definition: bearerbox.c:102
Counter * received
Definition: smscconn_p.h:162
void gwlist_insert(List *list, long pos, void *item)
Definition: list.c:214
Counter * sent_dlr
Definition: smscconn_p.h:165
static Cfg * cfg
Definition: smsbox.c:115
#define load_increase(load)
Definition: load.h:94
static Numhash * white_list_receiver
Definition: bb_smscconn.c:142
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
int smsc2_shutdown(void)
Definition: bb_smscconn.c:1268
void dict_destroy(Dict *dict)
Definition: dict.c:215
int cfg_get_bool(int *n, CfgGroup *grp, Octstr *varname)
Definition: cfg.c:756
Definition: octstr.c:118
void bb_smscconn_sent(SMSCConn *conn, Msg *sms, Octstr *reply)
Definition: bb_smscconn.c:279
int smscconn_usable(SMSCConn *conn, Msg *msg)
Definition: smscconn.c:514
static long sms_resend_frequency
Definition: bb_smscconn.c:152
int smsc2_graceful_restart(void)
Definition: bb_smscconn.c:1522
static int cmp_rout_grp_checksum(void *a, void *b)
Definition: bb_smscconn.c:752
Load * outgoing_dlr_load
Definition: smscconn_p.h:217
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
int cfg_get_integer(long *n, CfgGroup *grp, Octstr *varname)
Definition: cfg.c:739
volatile sig_atomic_t bb_status
Definition: bearerbox.c:132
#define panic
Definition: log.h:87
static List * split
Definition: test_http.c:88
void gwthread_wakeup(long thread)
Definition: cfg.c:73
Definition: load.c:76
void octstr_format_append(Octstr *os, const char *fmt,...)
Definition: octstr.c:2505
Msg * orig
Definition: msg.h:92
Load * incoming_dlr_load
Definition: smscconn_p.h:216
int smpp_pdu_init(Cfg *cfg)
Definition: smpp_pdu.c:150
List * dict_keys(Dict *dict)
Definition: dict.c:347
#define gwlist_create()
Definition: list.h:136
int normalize_number(char *dial_prefixes, Octstr **number)
Definition: utils.c:882
int total_parts
Definition: bb_smscconn.c:1983
SMSCConn * smscconn_create(CfgGroup *grp, int start_as_stopped)
Definition: smscconn.c:162
int(* store_save)(Msg *msg)
Definition: bb_store.c:72
Definition: thread.h:76
void bb_smscconn_send_failed(SMSCConn *conn, Msg *sms, int reason, Octstr *reply)
Definition: bb_smscconn.c:328
struct ConcatMsg ConcatMsg
static void destroy_concatMsg(void *x)
Definition: bb_smscconn.c:1997
Msg ** parts
Definition: bb_smscconn.c:1990
#define MAIN_THREAD_ID
Definition: gwthread.h:77
void smsc2_resume(int is_init)
Definition: bb_smscconn.c:1226
void gw_rwlock_init_static(RWLock *lock)
Definition: gw-rwlock.c:96
List * suspended
Definition: bearerbox.c:122
Octstr * smsc2_status(int status_type)
Definition: bb_smscconn.c:1354
static Octstr * unified_prefix
Definition: bb_smscconn.c:132
static Octstr * black_list_sender_url
Definition: bb_smscconn.c:135
int smscconn_info(SMSCConn *conn, StatusInfo *infotable)
Definition: smscconn.c:673
static Octstr * white_list_receiver_url
Definition: bb_smscconn.c:138
CfgGroup * cfg_get_single_group(Cfg *cfg, Octstr *name)
Definition: cfg.c:636
void gwlist_add_producer(List *list)
Definition: list.c:383
int smsc2_start(Cfg *cfg)
Definition: bb_smscconn.c:806
static void concat_handling_shutdown(void)
Definition: bb_smscconn.c:2026
static regex_t * black_list_sender_regex
Definition: bb_smscconn.c:145
#define DLR_SMSC_SUCCESS
Definition: dlr.h:75
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:404
#define mutex_lock(m)
Definition: thread.h:130
unsigned long received
Definition: smscconn.h:116
void * gwlist_timed_consume(List *list, long sec)
Definition: list.c:453
void octstr_set_char(Octstr *ostr, long pos, int ch)
Definition: octstr.c:413
int reroute_dlr
Definition: smscconn_p.h:209
static volatile sig_atomic_t smsc_running
Definition: bb_smscconn.c:127
int gw_rand(void)
Definition: protected.c:174
List * isolated
Definition: bearerbox.c:127
static volatile sig_atomic_t handle_concatenated_mo
Definition: bb_smscconn.c:162
Definition: list.c:102
static Numhash * black_list_receiver
Definition: bb_smscconn.c:141
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
static int start
static int concat_handling_check_and_handle(Msg **msg, Octstr *smscid)
Definition: bb_smscconn.c:2154
void smscconn_start(SMSCConn *conn)
Definition: smscconn.c:477
static List * smsc_list
Definition: bb_smscconn.c:128
static void reply(HTTPClient *c, List *push_headers)
int octstr_compare(const Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:869
static long smsc2_find(Octstr *id, long start)
Definition: bb_smscconn.c:948
long smsc2_rout(Msg *msg, int resend)
Definition: bb_smscconn.c:1710
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.