Kannel: Open Source WAP and SMS gateway  svn-r5335
bb_smscconn.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2018 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 {
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  */
206 }
207 
208 
209 static void handle_split(SMSCConn *conn, Msg *msg, long reason, Octstr *reply)
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  }
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, reply);
270  else {
271  debug("bb.sms.splits", 0, "Parts of concatenated message failed.");
272  bb_smscconn_send_failed(conn, msg, split->status, reply);
273  }
274  gw_free(split);
275  } else {
277  }
278 }
279 
280 
282 {
283  if (sms->sms.split_parts != NULL) {
284  handle_split(conn, sms, SMSCCONN_SUCCESS, reply);
285  return;
286  }
287 
288  /* write ACK to store file */
290 
291  if (sms->sms.sms_type != report_mt) {
292  bb_alog_sms(conn, sms, "Sent SMS");
295  if (conn != NULL) {
296  counter_increase(conn->sent);
298  }
299  } else {
300  bb_alog_sms(conn, sms, "Sent DLR");
303  if (conn != NULL) {
304  counter_increase(conn->sent_dlr);
306  }
307  }
308 
309  /* generate relay confirmancy message */
310  if (DLR_IS_SMSC_SUCCESS(sms->sms.dlr_mask)) {
311  Msg *dlrmsg;
312 
313  if (reply == NULL)
314  reply = octstr_create("");
315 
316  octstr_insert_data(reply, 0, "ACK/", 4);
317  dlrmsg = create_dlr_from_msg((conn->id?conn->id:conn->name), sms,
319  if (dlrmsg != NULL) {
320  bb_smscconn_receive(conn, dlrmsg);
321  }
322  }
323 
324  msg_destroy(sms);
326 }
327 
328 
329 void bb_smscconn_send_failed(SMSCConn *conn, Msg *sms, int reason, Octstr *reply)
330 {
331  if (sms->sms.split_parts != NULL) {
332  handle_split(conn, sms, reason, 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  }
358  break;
359 
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) || DLR_IS_FAIL(sms->sms.dlr_mask)) {
396  Msg *dlrmsg;
397 
398  if (reply == NULL)
399  reply = octstr_create("");
400 
401  octstr_insert_data(reply, 0, "NACK/", 5);
402  dlrmsg = create_dlr_from_msg((conn ? (conn->id?conn->id:conn->name) : NULL), sms,
404  if (dlrmsg != NULL) {
405  bb_smscconn_receive(conn, dlrmsg);
406  }
407  }
408 
409  msg_destroy(sms);
410  break;
411  }
412 
414 }
415 
416 static long bb_smscconn_receive_internal(SMSCConn *conn, Msg *sms)
417 {
418  int rc;
419  Msg *copy;
420 
421  copy = msg_duplicate(sms);
422 
423  /*
424  * Try to reroute internally to an smsc-id without leaving
425  * actually bearerbox scope.
426  * Scope: internal routing (to smsc-ids)
427  */
428  if ((rc = route_incoming_to_smsc(conn, copy)) == -1) {
429  /*
430  * Now try to route the message to a specific smsbox
431  * connection based on the existing msg->sms.boxc_id or
432  * the registered receiver numbers for specific smsbox'es.
433  * Scope: external routing (to smsbox connections)
434  */
435  rc = route_incoming_to_boxc(copy);
436  }
437 
438  if (rc == -1 || (rc != SMSCCONN_SUCCESS && rc != SMSCCONN_QUEUED)) {
439  warning(0, "incoming messages queue too long, dropping a message");
440  if (sms->sms.sms_type == report_mo)
441  bb_alog_sms(conn, sms, "DROPPED Received DLR");
442  else
443  bb_alog_sms(conn, sms, "DROPPED Received SMS");
444 
445  /* put nack into store-file */
447 
448  msg_destroy(copy);
449  msg_destroy(sms);
450  gwthread_sleep(0.1); /* letting the queue go down */
451  return (rc == -1 ? SMSCCONN_FAILED_QFULL : rc);
452  }
453 
454  if (sms->sms.sms_type != report_mo) {
455  bb_alog_sms(conn, sms, "Receive SMS");
458  if (conn != NULL) {
459  counter_increase(conn->received);
461  }
462  } else {
463  bb_alog_sms(conn, sms, "Receive DLR");
466  if (conn != NULL) {
469  }
470  }
471 
472  msg_destroy(sms);
473 
474  return SMSCCONN_SUCCESS;
475 }
476 
478 {
479  char *uf;
480  int ret;
481 
482  /*
483  * first check whether msgdata data is NULL and set it to empty
484  * because seems too much kannels parts rely on msgdata not to be NULL.
485  */
486  if (sms->sms.msgdata == NULL)
487  sms->sms.msgdata = octstr_create("");
488 
489  /*
490  * First normalize in smsc level and then on global level.
491  * In outbound direction it's vise versa, hence first global then smsc.
492  */
493  uf = (conn && conn->unified_prefix) ? octstr_get_cstr(conn->unified_prefix) : NULL;
494  normalize_number(uf, &(sms->sms.sender));
495 
497  normalize_number(uf, &(sms->sms.sender));
498 
499  /*
500  * We don't perform white/black-listing for DLRs.
501  * Fix sms type if not set already.
502  */
503  if (sms->sms.sms_type != report_mo) {
504  sms->sms.sms_type = mo;
505 
507  if (white_list_sender &&
508  numhash_find_number(white_list_sender, sms->sms.sender) < 1) {
510  info(0, "Number <%s> is not in white-list-sender, message discarded",
511  octstr_get_cstr(sms->sms.sender));
512  bb_alog_sms(conn, sms, "REJECTED Receive SMS - not white-listed SMS");
513  msg_destroy(sms);
515  }
516 
518  gw_regex_match_pre(white_list_sender_regex, sms->sms.sender) == 0) {
520  info(0, "Number <%s> is not in white-list-sender, message discarded",
521  octstr_get_cstr(sms->sms.sender));
522  bb_alog_sms(conn, sms, "REJECTED Receive SMS - not white-regex-listed SMS");
523  msg_destroy(sms);
525  }
526 
527  if (black_list_sender &&
528  numhash_find_number(black_list_sender, sms->sms.sender) == 1) {
530  info(0, "Number <%s> is in black-list-sender, message discarded",
531  octstr_get_cstr(sms->sms.sender));
532  bb_alog_sms(conn, sms, "REJECTED Receive SMS - black-listed SMS");
533  msg_destroy(sms);
535  }
536 
538  gw_regex_match_pre(black_list_sender_regex, sms->sms.sender) != 0) {
540  info(0, "Number <%s> is in black-list-sender, message discarded",
541  octstr_get_cstr(sms->sms.sender));
542  bb_alog_sms(conn, sms, "REJECTED Receive SMS - black-regex-listed SMS");
543  msg_destroy(sms);
545  }
546 
547  if (white_list_receiver &&
548  numhash_find_number(white_list_receiver, sms->sms.receiver) < 1) {
550  info(0, "Number <%s> is not in white-list-receiver, message discarded",
551  octstr_get_cstr(sms->sms.receiver));
552  bb_alog_sms(conn, sms, "REJECTED Receive SMS - not white-listed SMS");
553  msg_destroy(sms);
555  }
556 
558  gw_regex_match_pre(white_list_receiver_regex, sms->sms.receiver) == 0) {
560  info(0, "Number <%s> is not in white-list-receiver, message discarded",
561  octstr_get_cstr(sms->sms.receiver));
562  bb_alog_sms(conn, sms, "REJECTED Receive SMS - not white-regex-listed SMS");
563  msg_destroy(sms);
565  }
566 
567  if (black_list_receiver &&
568  numhash_find_number(black_list_receiver, sms->sms.receiver) == 1) {
570  info(0, "Number <%s> is in black-list-receiver, message discarded",
571  octstr_get_cstr(sms->sms.receiver));
572  bb_alog_sms(conn, sms, "REJECTED Receive SMS - black-listed SMS");
573  msg_destroy(sms);
575  }
576 
578  gw_regex_match_pre(black_list_receiver_regex, sms->sms.receiver) != 0) {
580  info(0, "Number <%s> is in black-list-receiver, message discarded",
581  octstr_get_cstr(sms->sms.receiver));
582  bb_alog_sms(conn, sms, "REJECTED Receive SMS - black-regex-listed SMS");
583  msg_destroy(sms);
585  }
587  }
588 
589  /* write to store (if enabled) */
590  if (store_save(sms) == -1) {
591  msg_destroy(sms);
593  }
594 
595  /* Before routing to some box or re-routing, do concatenation handling
596  * and replace copy as such.
597  */
598  if (handle_concatenated_mo && sms->sms.sms_type == mo) {
599  ret = concat_handling_check_and_handle(&sms, (conn ? conn->id : NULL));
600  switch(ret) {
601  case concat_pending:
604  if (conn != NULL) {
605  counter_increase(conn->received);
607  }
608  return SMSCCONN_SUCCESS;
609  case concat_complete:
610  /* Combined sms received! save new one since it is now combined. */
611  break;
612  case concat_error:
613  /* failed to save, go away. */
614  msg_destroy(sms);
616  case concat_none:
617  break;
618  default:
619  panic(0, "Internal error: Unhandled concat result.");
620  break;
621  }
622  }
623 
624  return bb_smscconn_receive_internal(conn, sms);
625 }
626 
628 {
629  debug("bb.sms", 0, "Reloading smsc groups list from config resource");
632  if (cfg_read(cfg_reloaded) == -1) {
633  warning(0, "Error opening configuration file %s", octstr_get_cstr(cfg_filename));
634  return -1;
635  }
638 
639  return 0;
640 }
641 
642 
643 /*---------------------------------------------------------------------
644  * Other functions
645  */
646 
647 /* function to route outgoing SMS'es from delay-list
648  * use some nice magics to route them to proper SMSC
649  */
650 static void sms_router(void *arg)
651 {
652  Msg *msg, *startmsg, *newmsg;
653  long ret;
654  time_t concat_mo_check;
655 
658 
659  startmsg = newmsg = NULL;
660  ret = SMSCCONN_SUCCESS;
661  concat_mo_check = time(NULL);
662 
663  while(bb_status != BB_SHUTDOWN && bb_status != BB_DEAD) {
664 
665  if (newmsg == startmsg) {
666  if (ret == SMSCCONN_QUEUED || ret == SMSCCONN_FAILED_QFULL) {
667  /* sleep: sms_resend_frequency / 2 , so we reduce amount of msgs to send */
668  double sleep_time = (sms_resend_frequency / 2 > 1 ? sms_resend_frequency / 2 : sms_resend_frequency);
669  debug("bb.sms", 0, "sms_router: time to sleep %.2f secs.", sleep_time);
670  gwthread_sleep(sleep_time);
671  debug("bb.sms", 0, "sms_router: gwlist_len = %ld", gwlist_len(outgoing_sms));
672  }
674  newmsg = NULL;
675  } else {
677  }
678 
679  if (difftime(time(NULL), concat_mo_check) > concatenated_mo_timeout) {
680  concat_mo_check = time(NULL);
682  }
683 
684  /* shutdown or timeout */
685  if (msg == NULL) {
686  newmsg = startmsg = NULL;
687  continue;
688  }
689 
690  debug("bb.sms", 0, "sms_router: handling message (%p vs %p)",
691  msg, startmsg);
692 
693  /* handle delayed msgs */
694  if (msg->sms.resend_try > 0 && difftime(time(NULL), msg->sms.resend_time) < sms_resend_frequency &&
696  debug("bb.sms", 0, "re-queing SMS not-yet-to-be resent");
698  ret = SMSCCONN_QUEUED;
699  continue;
700  }
701 
702  ret = smsc2_rout(msg, 1);
703  switch(ret) {
704  case SMSCCONN_SUCCESS:
705  debug("bb.sms", 0, "Message routed successfully.");
706  newmsg = startmsg = NULL;
707  break;
708  case SMSCCONN_QUEUED:
709  debug("bb.sms", 0, "Routing failed, re-queued.");
710  break;
712  msg_destroy(msg);
713  newmsg = startmsg = NULL;
714  break;
716  debug("bb.sms", 0, "Routing failed, re-queuing.");
718  break;
720  debug("bb.sms", 0, "Routing failed, expired.");
721  msg_destroy(msg);
722  newmsg = startmsg = NULL;
723  break;
724  default:
725  break;
726  }
727  }
729 }
730 
731 
732 #define OCTSTR(os) octstr_imm(#os)
733 
734 static int cmp_conn_grp_checksum(void *a, void *b)
735 {
736  int ret;
737  SMSCConn *conn = a;
738  Octstr *os;
739 
741  NULL
742  );
743 
744  ret = (octstr_compare(conn->chksum, os) == 0);
745  octstr_destroy(os);
746 
747  return ret;
748 }
749 
750 
751 static int cmp_rout_grp_checksum(void *a, void *b)
752 {
753  int ret;
754  SMSCConn *conn = a;
755  Octstr *os;
756 
758  OCTSTR(denied-smsc-id),
759  OCTSTR(allowed-smsc-id),
760  OCTSTR(preferred-smsc-id),
761  OCTSTR(allowed-prefix),
762  OCTSTR(denied-prefix),
763  OCTSTR(preferred-prefix),
764  OCTSTR(unified-prefix),
765  OCTSTR(reroute),
766  OCTSTR(reroute-smsc-id),
767  OCTSTR(reroute-receiver),
768  OCTSTR(reroute-receiver-regex),
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 */
820 
821  /* create smsc list and rwlock for it */
824 
825  grp = cfg_get_single_group(cfg, octstr_imm("core"));
826  unified_prefix = cfg_get(grp, octstr_imm("unified-prefix"));
827 
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) {
837  panic(0, "Could not get white-list at URL <%s>",
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) {
856  panic(0, "Could not get black-list at URL <%s>",
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 
871  white_list_receiver_url = cfg_get(grp, octstr_imm("white-list-receiver"));
872  if (white_list_receiver_url != NULL) {
874  panic(0, "Could not get white-list-receiver at URL <%s>",
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) {
886  panic(0, "Could not get black-list-receiver at URL <%s>",
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 
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  }
935 
936  if ((router_thread = gwthread_create(sms_router, NULL)) == -1)
937  panic(0, "Failed to start a new thread for SMS routing");
938 
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 
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  }
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 
1012 
1013  if (bb_reload_smsc_groups() != 0) {
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 
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 
1093 
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  }
1103 
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 = NULL;
1116  Octstr *smscid = NULL;
1117  long i, m, j;
1118  int success = 0;
1119 
1120  if (!smsc_running)
1121  return -1;
1122 
1124  if (bb_reload_smsc_groups() != 0) {
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));
1132  return -1;
1133  }
1134 
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  /* multiple instances for the same group? */
1145  m = smscconn_instances(grp);
1146  for (j = 0; j < m; j++) {
1147  conn = smscconn_create(grp, 1);
1148  if (conn != NULL) {
1149  gwlist_append(smsc_list, conn);
1150  if (conn->dead_start) {
1151  /* Shutdown connection if it's not configured to connect at start-up time */
1152  smscconn_shutdown(conn, 0);
1153  } else {
1154  smscconn_start(conn);
1155  }
1156  success = 1;
1157  } else {
1158  error(0, "Cannot start with SMSC %s connection failing", octstr_get_cstr(id));
1159  }
1160  }
1161  }
1162  octstr_destroy(smscid);
1163  smscid = NULL;
1164  }
1167  if (success == 0) {
1168  error(0, "SMSC %s not found", octstr_get_cstr(id));
1169  return -1;
1170  }
1171  return 0;
1172 }
1173 
1175 {
1176  Numhash *tmp;
1177  int rc = 1;
1178 
1179  if (white_list_sender_url != NULL) {
1181  if (white_list_sender == NULL) {
1182  error(0, "Unable to reload white_list."),
1183  rc = -1;
1184  } else {
1187  white_list_sender = tmp;
1189  }
1190  }
1191 
1192  if (black_list_sender_url != NULL) {
1194  if (black_list_sender == NULL) {
1195  error(0, "Unable to reload black_list");
1196  rc = -1;
1197  } else {
1200  black_list_sender = tmp;
1202  }
1203  }
1204 
1205  if (white_list_receiver_url != NULL) {
1207  if (white_list_receiver == NULL) {
1208  error(0, "Unable to reload white_list."),
1209  rc = -1;
1210  } else {
1213  white_list_receiver = tmp;
1215  }
1216  }
1217 
1218  if (black_list_receiver_url != NULL) {
1220  if (black_list_receiver == NULL) {
1221  error(0, "Unable to reload black_list");
1222  rc = -1;
1223  } else {
1226  black_list_receiver = tmp;
1228  }
1229  }
1230 
1231  return rc;
1232 }
1233 
1234 void smsc2_resume(int is_init)
1235 {
1236  SMSCConn *conn;
1237  long i;
1238 
1239  if (!smsc_running)
1240  return;
1241 
1243  for (i = 0; i < gwlist_len(smsc_list); i++) {
1244  conn = gwlist_get(smsc_list, i);
1245  if (!is_init || !conn->dead_start) {
1246  smscconn_start(conn);
1247  } else {
1248  /* Shutdown the connections that are not configured to start at boot */
1249  smscconn_shutdown(conn, 0);
1250  }
1251  }
1253 
1254  if (router_thread >= 0)
1256 }
1257 
1258 
1259 void smsc2_suspend(void)
1260 {
1261  SMSCConn *conn;
1262  long i;
1263 
1264  if (!smsc_running)
1265  return;
1266 
1268  for (i = 0; i < gwlist_len(smsc_list); i++) {
1269  conn = gwlist_get(smsc_list, i);
1270  smscconn_stop(conn);
1271  }
1273 }
1274 
1275 
1277 {
1278  SMSCConn *conn;
1279  long i;
1280 
1281  if (!smsc_running)
1282  return -1;
1283 
1284  /* stop concat handling */
1286 
1287  /* Call shutdown for all SMSC Connections; they should
1288  * handle that they quit, by emptying queues and then dying off
1289  */
1291  for(i=0; i < gwlist_len(smsc_list); i++) {
1292  conn = gwlist_get(smsc_list, i);
1293  smscconn_shutdown(conn, 1);
1294  }
1296  if (router_thread >= 0)
1298 
1299  /* start avalanche by calling shutdown */
1300 
1301  /* XXX shouldn'w we be sure that all smsces have closed their
1302  * receive thingies? Is this guaranteed by setting bb_status
1303  * to shutdown before calling these?
1304  */
1306 
1307  /* shutdown low levele PDU things */
1309 
1310  return 0;
1311 }
1312 
1313 
1314 void smsc2_cleanup(void)
1315 {
1316  SMSCConn *conn;
1317  long i;
1318 
1319  if (!smsc_running)
1320  return;
1321 
1322  debug("smscconn", 0, "final clean-up for SMSCConn");
1323 
1325  for (i = 0; i < gwlist_len(smsc_list); i++) {
1326  conn = gwlist_get(smsc_list, i);
1327  smscconn_destroy(conn);
1328  }
1329  gwlist_destroy(smsc_list, NULL);
1330  smsc_list = NULL;
1332  gwlist_destroy(smsc_groups, NULL);
1338  if (white_list_sender_regex != NULL)
1339  gw_regex_destroy(white_list_sender_regex);
1340  if (black_list_sender_regex != NULL)
1341  gw_regex_destroy(black_list_sender_regex);
1346  if (white_list_receiver_regex != NULL)
1347  gw_regex_destroy(white_list_receiver_regex);
1348  if (black_list_receiver_regex != NULL)
1349  gw_regex_destroy(black_list_receiver_regex);
1350  /* destroy msg split counter */
1354 
1355  /* Stop concat handling */
1357 
1358  smsc_running = 0;
1359 }
1360 
1361 
1362 Octstr *smsc2_status(int status_type)
1363 {
1364  Octstr *tmp;
1365  char tmp3[64];
1366  char *lb;
1367  long i;
1368  int para = 0;
1369  SMSCConn *conn;
1370  StatusInfo info;
1371  const Octstr *conn_id = NULL;
1372  const Octstr *conn_admin_id = NULL;
1373  const Octstr *conn_name = NULL;
1374  float incoming_sms_load_0, incoming_sms_load_1, incoming_sms_load_2;
1375  float outgoing_sms_load_0, outgoing_sms_load_1, outgoing_sms_load_2;
1376  float incoming_dlr_load_0, incoming_dlr_load_1, incoming_dlr_load_2;
1377  float outgoing_dlr_load_0, outgoing_dlr_load_1, outgoing_dlr_load_2;
1378 
1379  if ((lb = bb_status_linebreak(status_type)) == NULL)
1380  return octstr_create("Un-supported format");
1381 
1382  if (status_type == BBSTATUS_HTML || status_type == BBSTATUS_WML)
1383  para = 1;
1384 
1385  if (!smsc_running) {
1386  if (status_type == BBSTATUS_XML)
1387  return octstr_create ("<smscs>\n\t<count>0</count>\n</smscs>");
1388  else
1389  return octstr_format("%sNo SMSC connections%s\n\n", para ? "<p>" : "",
1390  para ? "</p>" : "");
1391  }
1392 
1393  if (status_type != BBSTATUS_XML)
1394  tmp = octstr_format("%sSMSC connections:%s", para ? "<p>" : "", lb);
1395  else
1396  tmp = octstr_format("<smscs><count>%d</count>\n\t", gwlist_len(smsc_list));
1397 
1399  for (i = 0; i < gwlist_len(smsc_list); i++) {
1400  incoming_sms_load_0 = incoming_sms_load_1 = incoming_sms_load_2 = 0.0;
1401  outgoing_sms_load_0 = outgoing_sms_load_1 = outgoing_sms_load_2 = 0.0;
1402  incoming_dlr_load_0 = incoming_dlr_load_1 = incoming_dlr_load_2 = 0.0;
1403  outgoing_dlr_load_0 = outgoing_dlr_load_1 = outgoing_dlr_load_2 = 0.0;
1404  conn = gwlist_get(smsc_list, i);
1405 
1406  if ((smscconn_info(conn, &info) == -1)) {
1407  /*
1408  * we do not delete SMSCs from the list
1409  * this way we can show in the status which links are dead
1410  */
1411  continue;
1412  }
1413 
1414  conn_id = conn ? smscconn_id(conn) : octstr_imm("unknown");
1415  conn_id = conn_id ? conn_id : octstr_imm("unknown");
1416  conn_admin_id = conn ? smscconn_admin_id(conn) : octstr_imm("unknown");
1417  conn_admin_id = conn_admin_id ? conn_admin_id : octstr_imm("unknown");
1418  conn_name = conn ? smscconn_name(conn) : octstr_imm("unknown");
1419 
1420  if (status_type == BBSTATUS_HTML) {
1421  octstr_append_cstr(tmp, "&nbsp;&nbsp;&nbsp;&nbsp;<b>");
1422  octstr_append(tmp, conn_id);
1423  octstr_append_cstr(tmp, "</b>[");
1424  octstr_append(tmp, conn_admin_id);
1425  octstr_append_cstr(tmp, "]&nbsp;&nbsp;&nbsp;&nbsp;");
1426  } else if (status_type == BBSTATUS_TEXT) {
1427  octstr_append_cstr(tmp, " ");
1428  octstr_append(tmp, conn_id);
1429  octstr_append_cstr(tmp, "[");
1430  octstr_append(tmp, conn_admin_id);
1431  octstr_append_cstr(tmp, "] ");
1432  }
1433  if (status_type == BBSTATUS_XML) {
1434  octstr_append_cstr(tmp, "<smsc>\n\t\t<name>");
1435  octstr_append(tmp, conn_name);
1436  octstr_append_cstr(tmp, "</name>\n\t\t<admin-id>");
1437  octstr_append(tmp, conn_admin_id);
1438  octstr_append_cstr(tmp, "</admin-id>\n\t\t<id>");
1439  octstr_append(tmp, conn_id);
1440  octstr_append_cstr(tmp, "</id>\n\t\t");
1441  } else
1442  octstr_append(tmp, conn_name);
1443 
1444  switch (info.status) {
1445  case SMSCCONN_ACTIVE:
1446  case SMSCCONN_ACTIVE_RECV:
1447  sprintf(tmp3, "online %lds", info.online);
1448  incoming_sms_load_0 = load_get(conn->incoming_sms_load,0);
1449  incoming_sms_load_1 = load_get(conn->incoming_sms_load,1);
1450  incoming_sms_load_2 = load_get(conn->incoming_sms_load,2);
1451  outgoing_sms_load_0 = load_get(conn->outgoing_sms_load,0);
1452  outgoing_sms_load_1 = load_get(conn->outgoing_sms_load,1);
1453  outgoing_sms_load_2 = load_get(conn->outgoing_sms_load,2);
1454  incoming_dlr_load_0 = load_get(conn->incoming_dlr_load,0);
1455  incoming_dlr_load_1 = load_get(conn->incoming_dlr_load,1);
1456  incoming_dlr_load_2 = load_get(conn->incoming_dlr_load,2);
1457  outgoing_dlr_load_0 = load_get(conn->outgoing_dlr_load,0);
1458  outgoing_dlr_load_1 = load_get(conn->outgoing_dlr_load,1);
1459  outgoing_dlr_load_2 = load_get(conn->outgoing_dlr_load,2);
1460  break;
1461  case SMSCCONN_DISCONNECTED:
1462  sprintf(tmp3, "disconnected");
1463  break;
1464  case SMSCCONN_CONNECTING:
1465  sprintf(tmp3, "connecting");
1466  break;
1467  case SMSCCONN_RECONNECTING:
1468  sprintf(tmp3, "re-connecting");
1469  break;
1470  case SMSCCONN_DEAD:
1471  sprintf(tmp3, "dead");
1472  break;
1473  default:
1474  sprintf(tmp3, "unknown");
1475  break;
1476  }
1477 
1478  if (status_type == BBSTATUS_XML)
1479  octstr_format_append(tmp, "<status>%s</status>\n"
1480  "\t\t<failed>%ld</failed>\n"
1481  "\t\t<queued>%ld</queued>\n"
1482  "\t\t<sms>\n"
1483  "\t\t\t<received>%ld</received>\n"
1484  "\t\t\t<sent>%ld</sent>\n"
1485  "\t\t\t<inbound>%.2f,%.2f,%.2f</inbound>\n"
1486  "\t\t\t<outbound>%.2f,%.2f,%.2f</outbound>\n"
1487  "\t\t</sms>\n\t\t<dlr>\n"
1488  "\t\t\t<received>%ld</received>\n"
1489  "\t\t\t<sent>%ld</sent>\n"
1490  "\t\t\t<inbound>%.2f,%.2f,%.2f</inbound>\n"
1491  "\t\t\t<outbound>%.2f,%.2f,%.2f</outbound>\n"
1492  "\t\t</dlr>\n"
1493  "\t</smsc>\n", tmp3,
1494  info.failed, info.queued, info.received, info.sent,
1495  incoming_sms_load_0, incoming_sms_load_1, incoming_sms_load_2,
1496  outgoing_sms_load_0, outgoing_sms_load_1, outgoing_sms_load_2,
1497  info.received_dlr, info.sent_dlr,
1498  incoming_dlr_load_0, incoming_dlr_load_1, incoming_dlr_load_2,
1499  outgoing_dlr_load_0, outgoing_dlr_load_1, outgoing_dlr_load_2);
1500  else
1501  octstr_format_append(tmp, " (%s, rcvd: sms %ld (%.2f,%.2f,%.2f) / dlr %ld (%.2f,%.2f,%.2f), "
1502  "sent: sms %ld (%.2f,%.2f,%.2f) / dlr %ld (%.2f,%.2f,%.2f), failed %ld, "
1503  "queued %ld msgs)%s",
1504  tmp3,
1505  info.received,
1506  incoming_sms_load_0, incoming_sms_load_1, incoming_sms_load_2,
1507  info.received_dlr,
1508  incoming_dlr_load_0, incoming_dlr_load_1, incoming_dlr_load_2,
1509  info.sent,
1510  outgoing_sms_load_0, outgoing_sms_load_1, outgoing_sms_load_2,
1511  info.sent_dlr,
1512  outgoing_dlr_load_0, outgoing_dlr_load_1, outgoing_dlr_load_2,
1513  info.failed,
1514  info.queued,
1515  lb);
1516  }
1517 
1519 
1520  if (para)
1521  octstr_append_cstr(tmp, "</p>");
1522  if (status_type == BBSTATUS_XML)
1523  octstr_append_cstr(tmp, "</smscs>\n");
1524  else
1525  octstr_append_cstr(tmp, "\n\n");
1526  return tmp;
1527 }
1528 
1529 
1531 {
1532  CfgGroup *grp;
1533  SMSCConn *conn;
1534  List *keep, *add, *remove;
1535  List *l;
1536  int i, m;
1537 
1538  if (!smsc_running)
1539  return -1;
1540 
1542 
1543  /* load the smsc groups from the config resource */
1544  gwlist_destroy(smsc_groups, NULL);
1546 
1547  /* List of SMSCConn that we keep running */
1548  keep = gwlist_create();
1549 
1550  /* List of CfgGroup that we will add */
1551  add = gwlist_create();
1552 
1553  /* List of SMSCConnn that we will shutdown */
1554  remove = gwlist_create();
1555 
1556  /*
1557  * Loop through the loaded smsc groups
1558  */
1559  for (i = 0; i < gwlist_len(smsc_groups) &&
1560  (grp = gwlist_get(smsc_groups, i)) != NULL; i++) {
1561  /*
1562  * 1st check: Search for the same md5 hash of the whole group.
1563  * If we find it, then this group is already running, and no
1564  * routing information has changed, bail out.
1565  */
1566  if ((l = gwlist_search_all(smsc_list, grp, cmp_conn_grp_checksum)) != NULL) {
1567  while ((conn = gwlist_extract_first(l)) != NULL) {
1568  gwlist_append(keep, conn);
1569  }
1570  gwlist_destroy(l, NULL);
1571  continue;
1572  }
1573  /*
1574  * 2nd check: Search for the same md5 hash minus the routing
1575  * information. If we find it, then this group is already running
1576  * and the routing information changed, we'll apply only the new
1577  * routing information.
1578  */
1579  if ((l = gwlist_search_all(smsc_list, grp, cmp_rout_grp_checksum)) != NULL) {
1580  while ((conn = gwlist_extract_first(l)) != NULL) {
1581  gwlist_append(keep, conn);
1582  smscconn_reconfig(conn, grp);
1583  info(0, "Re-configured routing for smsc-id `%s'.", octstr_get_cstr(conn->id));
1584  }
1585  gwlist_destroy(l, NULL);
1586  continue;
1587  }
1588  /*
1589  * 3rd check: if the smsc-id is NOT in the running list, then
1590  * this is a new group, add it. If the smsc-id IS found, then
1591  * mark it/them to be removed, and add the new group.
1592  */
1593  if ((l = gwlist_search_all(smsc_list, grp, cmp_conn_grp_id)) == NULL) {
1594  gwlist_append(add, grp);
1595  continue;
1596  } else {
1597  while ((conn = gwlist_extract_first(l)) != NULL) {
1598  /* add them to the remove list only
1599  * if they are not yet present inside. */
1600  if (gwlist_search_equal(remove, conn) != -1)
1601  gwlist_append(remove, conn);
1602  }
1603  gwlist_destroy(l, NULL);
1604  gwlist_append(add, grp);
1605  continue;
1606  }
1607  }
1608 
1609  /*
1610  * TODO Effectively a change in the 'instances' multiplier will result in a
1611  * disconnect of all running instances, and re-connecting the number of
1612  * configured instances. The reason for this is that the change in the
1613  * 'instances' value causes the md5 hash to be different for that connection.
1614  * We MAY exclude the 'instances' directive from the while md5 checksum, this
1615  * makes the down-grading easier, allowing the rest to keep running. But the
1616  * up-grading is more difficult, since we can't use the 'add' list here, it
1617  * would create too much instances.
1618  */
1619 
1620  /*
1621  * We may have running smsc-ids now, that haven't been
1622  * re-loaded from the new config, hence add them to be removed.
1623  */
1624  for (i = 0; i < gwlist_len(smsc_list) &&
1625  (conn = gwlist_get(smsc_list, i)) != NULL; i++) {
1626  /* if this is already in the remove list, bail out. */
1627  if (gwlist_search_equal(remove, conn) != -1)
1628  continue;
1629  /* if this is in the keep list, bail out. */
1630  if (gwlist_search_equal(keep, conn) != -1)
1631  continue;
1632  /* mark it to be removed */
1633  gwlist_append(remove, conn);
1634  }
1635  gwlist_destroy(keep, NULL);
1636 
1637  /*
1638  * Stop any connections from the remove list.
1639  *
1640  * The smscconn_shutdown() only initiates the shutdown,
1641  * it is not guaranteed that the SMSC connection is stopped
1642  * and the status is SMSCCONN_DEAD when we return from the
1643  * function call. Therefore we pass the connection to a
1644  * retry list, in order to cleanly destroy all connection
1645  * structures that have been stopped and reached SMSSCONN_DEAD.
1646  */
1647  l = gwlist_create();
1649  while ((conn = gwlist_extract_first(remove)) != NULL) {
1650  if ((i = gwlist_search_equal(smsc_list, conn)) != -1) {
1651  gwlist_delete(smsc_list, i, 1);
1652  smscconn_shutdown(conn, 0);
1653  /* if smsc is still in shutdown, then add to retry list */
1654  if (smscconn_destroy(conn) == -1)
1655  gwlist_append(l, conn);
1656  }
1657  }
1659  gwlist_destroy(remove, NULL);
1660 
1661  /*
1662  * Start any connections from the add list.
1663  */
1665  while ((grp = gwlist_extract_first(add)) != NULL) {
1666  /* multiple instances for the same group? */
1667  m = smscconn_instances(grp);
1668  for (i = 0; i < m; i++) {
1669  conn = smscconn_create(grp, 1);
1670  if (conn != NULL) {
1671  gwlist_append(smsc_list, conn);
1672  if (conn->dead_start) {
1673  /* Shutdown connection if it's not configured to connect at start-up time */
1674  smscconn_shutdown(conn, 0);
1675  } else {
1676  smscconn_start(conn);
1677  }
1678  }
1679  }
1680  }
1682  gwlist_destroy(add, NULL);
1683 
1685 
1686  /* wake-up the router */
1687  if (router_thread >= 0)
1689 
1690  /*
1691  * We may still have pending connections in the retry list
1692  * that haven't been destroyed yet.
1693  */
1694  while ((conn = gwlist_extract_first(l)) != NULL) {
1695  if (smscconn_destroy(conn) == -1) {
1696  gwlist_append(l, conn);
1697  gwthread_sleep(2);
1698  }
1699  }
1700  gwlist_destroy(l, NULL);
1701 
1702  return 0;
1703 }
1704 
1705 
1706 /* function to route outgoing SMS'es
1707  *
1708  * If finds a good one, puts into it and returns SMSCCONN_SUCCESS
1709  * If finds only bad ones, but acceptable, queues and
1710  * returns SMSCCONN_QUEUED (like all acceptable currently disconnected)
1711  * if message acceptable but queues full returns SMSCCONN_FAILED_QFULL and
1712  * message is not destroyed.
1713  * If cannot find nothing at all, returns SMSCCONN_FAILED_DISCARDED and
1714  * message is NOT destroyed (otherwise it is)
1715  */
1716 long smsc2_rout(Msg *msg, int resend)
1717 {
1718  StatusInfo stat;
1719  SMSCConn *conn, *best_preferred, *best_ok;
1720  long bp_load, bo_load;
1721  int i, s, ret, bad_found, full_found;
1722  long max_queue, queue_length;
1723  char *uf;
1724 
1725  /* XXX handle ack here? */
1726  if (msg_type(msg) != sms) {
1727  error(0, "Attempt to route non SMS message through smsc2_rout!");
1729  }
1730 
1731  /* check if validity period has expired */
1732  if (msg->sms.validity != SMS_PARAM_UNDEFINED && time(NULL) > msg->sms.validity) {
1734  return SMSCCONN_FAILED_EXPIRED;
1735  }
1736 
1737  /* unify prefix of receiver, in case of it has not been
1738  * already done */
1740  normalize_number(uf, &(msg->sms.receiver));
1741 
1742  /* check for white/back-listed sender/receiver */
1744  if (white_list_sender && numhash_find_number(white_list_sender, msg->sms.sender) < 1) {
1746  info(0, "Number <%s> is not in white-list-sender, message rejected",
1747  octstr_get_cstr(msg->sms.sender));
1748  bb_smscconn_send_failed(NULL, msg_duplicate(msg), SMSCCONN_FAILED_REJECTED, octstr_create("sender not in white-list"));
1749  return SMSCCONN_FAILED_REJECTED;
1750  }
1751 
1752  if (white_list_sender_regex && gw_regex_match_pre(white_list_sender_regex, msg->sms.sender) == 0) {
1754  info(0, "Number <%s> is not in white-list-sender, message rejected",
1755  octstr_get_cstr(msg->sms.sender));
1756  bb_smscconn_send_failed(NULL, msg_duplicate(msg), SMSCCONN_FAILED_REJECTED, octstr_create("sender not in white-list"));
1757  return SMSCCONN_FAILED_REJECTED;
1758  }
1759 
1760  if (black_list_sender && numhash_find_number(black_list_sender, msg->sms.sender) == 1) {
1762  info(0, "Number <%s> is in black-list-sender, message rejected",
1763  octstr_get_cstr(msg->sms.sender));
1765  return SMSCCONN_FAILED_REJECTED;
1766  }
1767 
1768  if (black_list_sender_regex && gw_regex_match_pre(black_list_sender_regex, msg->sms.sender) != 0) {
1770  info(0, "Number <%s> is in black-list-sender, message rejected",
1771  octstr_get_cstr(msg->sms.sender));
1773  return SMSCCONN_FAILED_REJECTED;
1774  }
1775 
1776  if (white_list_receiver && numhash_find_number(white_list_receiver, msg->sms.receiver) < 1) {
1778  info(0, "Number <%s> is not in white-list-receiver, message rejected",
1779  octstr_get_cstr(msg->sms.receiver));
1780  bb_smscconn_send_failed(NULL, msg_duplicate(msg), SMSCCONN_FAILED_REJECTED, octstr_create("receiver not in white-list"));
1781  return SMSCCONN_FAILED_REJECTED;
1782  }
1783 
1784  if (white_list_receiver_regex && gw_regex_match_pre(white_list_receiver_regex, msg->sms.receiver) == 0) {
1786  info(0, "Number <%s> is not in white-list-receiver, message rejected",
1787  octstr_get_cstr(msg->sms.receiver));
1788  bb_smscconn_send_failed(NULL, msg_duplicate(msg), SMSCCONN_FAILED_REJECTED, octstr_create("receiver not in white-list"));
1789  return SMSCCONN_FAILED_REJECTED;
1790  }
1791 
1792  if (black_list_receiver && numhash_find_number(black_list_receiver, msg->sms.receiver) == 1) {
1794  info(0, "Number <%s> is in black-list-receiver, message rejected",
1795  octstr_get_cstr(msg->sms.receiver));
1797  return SMSCCONN_FAILED_REJECTED;
1798  }
1799 
1800  if (black_list_receiver_regex && gw_regex_match_pre(black_list_receiver_regex, msg->sms.receiver) != 0) {
1802  info(0, "Number <%s> is in black-list-receiver, message rejected",
1803  octstr_get_cstr(msg->sms.receiver));
1805  return SMSCCONN_FAILED_REJECTED;
1806  }
1808 
1809  /* select in which list to add this
1810  * start - from random SMSCConn, as they are all 'equal'
1811  */
1813  if (gwlist_len(smsc_list) == 0) {
1814  warning(0, "No SMSCes to receive message");
1817  }
1818 
1819  best_preferred = best_ok = NULL;
1820  bad_found = full_found = 0;
1821  bp_load = bo_load = queue_length = 0;
1822 
1823  if (msg->sms.split_parts == NULL) {
1824  /*
1825  * if global queue not empty then 20% reserved for old msgs
1826  * and 80% for new msgs. So we can guarantee that old msgs find
1827  * place in the SMSC's queue.
1828  */
1829  if (gwlist_len(outgoing_sms) > 0) {
1830  max_queue = (resend ? max_outgoing_sms_qlength :
1831  max_outgoing_sms_qlength * 0.8);
1832  } else
1833  max_queue = max_outgoing_sms_qlength;
1834 
1835  s = gw_rand() % gwlist_len(smsc_list);
1836 
1837  conn = NULL;
1838  for (i = 0; i < gwlist_len(smsc_list); i++) {
1839  conn = gwlist_get(smsc_list, (i+s) % gwlist_len(smsc_list));
1840 
1841  smscconn_info(conn, &stat);
1842  queue_length += (stat.queued > 0 ? stat.queued : 0);
1843 
1844  ret = smscconn_usable(conn,msg);
1845  if (ret == -1)
1846  continue;
1847 
1848  /* if we already have a preferred one, skip non-preferred */
1849  if (ret != 1 && best_preferred)
1850  continue;
1851 
1852  /* If connection is not currently answering ... */
1853  if (stat.status != SMSCCONN_ACTIVE) {
1854  bad_found = 1;
1855  continue;
1856  }
1857  /* check queue length */
1858  if (stat.queued > max_queue) {
1859  full_found = 1;
1860  continue;
1861  }
1862  if (ret == 1) { /* preferred */
1863  if (best_preferred == NULL || stat.load < bp_load) {
1864  best_preferred = conn;
1865  bp_load = stat.load;
1866  continue;
1867  }
1868  }
1869  if (best_ok == NULL || stat.load < bo_load) {
1870  best_ok = conn;
1871  bo_load = stat.load;
1872  }
1873  }
1874  queue_length += gwlist_len(outgoing_sms);
1875  if (max_outgoing_sms_qlength > 0 && !resend &&
1876  queue_length > gwlist_len(smsc_list) * max_outgoing_sms_qlength) {
1878  debug("bb.sms", 0, "sum(#queues) limit");
1879  return SMSCCONN_FAILED_QFULL;
1880  }
1881  } else {
1882  struct split_parts *parts = msg->sms.split_parts;
1883  /* check whether this SMSCConn still on the list */
1884  if (gwlist_search_equal(smsc_list, parts->smsc_conn) != -1)
1885  best_preferred = parts->smsc_conn;
1886  }
1887 
1888  if (best_preferred)
1889  ret = smscconn_send(best_preferred, msg);
1890  else if (best_ok)
1891  ret = smscconn_send(best_ok, msg);
1892  else if (bad_found) {
1896  return SMSCCONN_QUEUED;
1897  }
1898  debug("bb.sms", 0, "bad_found queue full");
1899  return SMSCCONN_FAILED_QFULL; /* queue full */
1900  } else if (full_found) {
1902  debug("bb.sms", 0, "full_found queue full");
1903  return SMSCCONN_FAILED_QFULL;
1904  } else {
1906  if (bb_status == BB_SHUTDOWN) {
1907  msg_destroy(msg);
1908  return SMSCCONN_QUEUED;
1909  }
1910  warning(0, "Cannot find SMSCConn for message to <%s>, rejected.",
1911  octstr_get_cstr(msg->sms.receiver));
1914  }
1915 
1917  /* check the status of sending operation */
1918  if (ret == -1)
1919  return smsc2_rout(msg, resend); /* re-try */
1920 
1921  msg_destroy(msg);
1922  return SMSCCONN_SUCCESS;
1923 }
1924 
1925 
1926 /*
1927  * Try to reroute to another smsc.
1928  * @return -1 if no rerouting info available; otherwise return code from smsc2_route.
1929  */
1931 {
1932  Octstr *smsc;
1933 
1934  /* sanity check */
1935  if (!conn || !msg)
1936  return -1;
1937 
1938  /* check for dlr rerouting */
1939  if (!conn->reroute_dlr && (msg->sms.sms_type == report_mo || msg->sms.sms_type == report_mt))
1940  return -1;
1941 
1942  /*
1943  * Check if we have any "reroute" rules to obey. Which means msg gets
1944  * transported internally from MO to MT msg.
1945  */
1946  if (conn->reroute) {
1947  /* change message direction */
1949  msg->sms.sms_type = mt_push;
1950  store_save(msg);
1951  /* drop into outbound queue again for routing */
1952  return smsc2_rout(msg, 0);
1953  }
1954 
1955  if (conn->reroute_to_smsc) {
1956  /* change message direction */
1958  msg->sms.sms_type = mt_push;
1959  store_save(msg);
1960  /* apply directly to the given smsc-id for MT traffic */
1961  octstr_destroy(msg->sms.smsc_id);
1962  msg->sms.smsc_id = octstr_duplicate(conn->reroute_to_smsc);
1963  return smsc2_rout(msg, 0);
1964  }
1965 
1966  if (conn->reroute_by_receiver && msg->sms.receiver &&
1967  (smsc = dict_get(conn->reroute_by_receiver, msg->sms.receiver))) {
1968  /* change message direction */
1970  msg->sms.sms_type = mt_push;
1971  store_save(msg);
1972  /* route by receiver number */
1973  octstr_destroy(msg->sms.smsc_id);
1974  msg->sms.smsc_id = octstr_duplicate(smsc);
1975  return smsc2_rout(msg, 0);
1976  }
1977 
1978  if (conn->reroute_by_receiver_regex && msg->sms.receiver) {
1979  int i, l;
1980  pattern_route *r;
1981 
1983  for (i = 0; i < l; i++) {
1984  r = gwlist_get(conn->reroute_by_receiver_regex, i);
1985  /* match against regex pattern */
1986  if (r != NULL && r->re != NULL &&
1987  gw_regex_match_pre(r->re, msg->sms.receiver) == 1) {
1988  /* matched, change message direction */
1990  msg->sms.sms_type = mt_push;
1991  store_save(msg);
1992  /* route by receiver number */
1993  octstr_destroy(msg->sms.smsc_id);
1994  msg->sms.smsc_id = octstr_duplicate(r->id);
1995  return smsc2_rout(msg, 0);
1996  }
1997  }
1998  }
1999 
2000  return -1;
2001 }
2002 
2003 
2004 /*--------------------------------
2005  * incoming concatenated messages handling
2006  */
2007 
2008 typedef struct ConcatMsg {
2009  int refnum;
2012  Octstr *udh; /* normalized UDH */
2013  time_t trecv;
2014  Octstr *key; /* in dict. */
2015  int ack; /* set to the type of ack to send when deleting. */
2016  /* array of parts */
2018  Octstr *smsc_id; /* name of smsc conn where we received this msgs */
2019 } ConcatMsg;
2020 
2023 
2024 static void destroy_concatMsg(void *x)
2025 {
2026  int i;
2027  ConcatMsg *msg = x;
2028 
2029  gw_assert(msg);
2030  for (i = 0; i < msg->total_parts; i++) {
2031  if (msg->parts[i]) {
2032  store_save_ack(msg->parts[i], msg->ack);
2033  msg_destroy(msg->parts[i]);
2034  }
2035  }
2036  gw_free(msg->parts);
2037  octstr_destroy(msg->key);
2038  octstr_destroy(msg->udh);
2039  octstr_destroy(msg->smsc_id);
2040  gw_free(msg);
2041 }
2042 
2043 static void concat_handling_init(void)
2044 {
2045  if (incoming_concat_msgs != NULL) /* already initialised? */
2046  return;
2050  debug("bb.sms",0,"MO concatenated message handling enabled");
2051 }
2052 
2053 static void concat_handling_shutdown(void)
2054 {
2055  /* check if we were enabled at all? */
2057  return;
2058 
2059  /* deactivate */
2061 
2062  /* go through the queue and send messages as is */
2064 }
2065 
2066 static void concat_handling_cleanup(void)
2067 {
2068  if (incoming_concat_msgs == NULL)
2069  return;
2072 
2073  incoming_concat_msgs = NULL;
2074  concat_lock = NULL;
2075  debug("bb.sms",0,"MO concatenated message handling cleaned up");
2076 }
2077 
2078 static void concat_handling_clear_old_parts(int force)
2079 {
2080  List *keys;
2081  Octstr *key;
2082 
2083  /* not initialized, go away */
2084  if (incoming_concat_msgs == NULL)
2085  return;
2086 
2087  debug("bb.sms.splits", 0, "clear_old_concat_parts called");
2088 
2089  /* Remove any pending messages that are too old. */
2091  while((key = gwlist_extract_first(keys)) != NULL) {
2092  ConcatMsg *x;
2093  Msg *msg;
2094  SMSCConn *conn;
2095  int i, destroy = 1, smsc_index;
2096 
2098  x = dict_get(incoming_concat_msgs, key);
2099  octstr_destroy(key);
2100  if (x == NULL || (!force && difftime(time(NULL), x->trecv) < concatenated_mo_timeout)) {
2102  continue;
2103  }
2106 
2107  /* try to find SMSCConn */
2112  smsc_index = smsc2_find(x->smsc_id, 0);
2113  if (smsc_index != -1) {
2114  conn = gwlist_get(smsc_list, smsc_index);
2115  warning(0, "Time-out waiting for concatenated message '%s'. Send message parts as is.",
2116  octstr_get_cstr(x->key));
2117  for (i = 0; i < x->total_parts && destroy == 1; i++) {
2118  if (x->parts[i] == NULL)
2119  continue;
2120  msg = msg_duplicate(x->parts[i]);
2121  switch(bb_smscconn_receive_internal(conn, msg)) {
2123  case SMSCCONN_QUEUED:
2124  case SMSCCONN_SUCCESS:
2125  msg_destroy(x->parts[i]);
2126  x->parts[i] = NULL;
2127  x->num_parts--;
2128  break;
2130  case SMSCCONN_FAILED_QFULL:
2131  default:
2132  /* oops put it back into dict and retry on next run */
2133  store_save(x->parts[i]);
2134  destroy = 0;
2135  break;
2136  }
2137  }
2138  }
2140 
2141  if (destroy) {
2142  destroy_concatMsg(x);
2143  } else {
2144  ConcatMsg *x1;
2146  x1 = dict_get(incoming_concat_msgs, x->key);
2147  if (x1 != NULL) { /* oops we have new part */
2148  int i;
2149  if (x->total_parts != x1->total_parts) {
2150  /* broken handset, don't know what todo here??
2151  * for now just put old concatMsg into dict with
2152  * another key and it will be cleaned up on next run.
2153  */
2154  octstr_format_append(x->key, " %d", x->total_parts);
2156  } else {
2157  for (i = 0; i < x->total_parts; i++) {
2158  if (x->parts[i] == NULL)
2159  continue;
2160  if (x1->parts[i] == NULL) {
2161  x1->parts[i] = x->parts[i];
2162  x->parts[i] = NULL;
2163  }
2164  }
2165  destroy_concatMsg(x);
2166  }
2167  } else {
2169  }
2171  }
2172  }
2174 }
2175 
2176 /* Checks if message is concatenated. Returns:
2177  * - returns concat_complete if no concat parts, or message complete
2178  * - returns concat_pending (and sets *pmsg to NULL) if parts pending
2179  * - returns concat_error if store_save fails
2180  */
2181 static int concat_handling_check_and_handle(Msg **pmsg, Octstr *smscid)
2182 {
2183  Msg *msg = *pmsg;
2184  int l, iel = 0, refnum, pos, c, part, totalparts, i, sixteenbit;
2185  Octstr *udh = msg->sms.udhdata, *key;
2186  ConcatMsg *cmsg;
2187  int ret = concat_complete;
2188 
2190  return concat_none;
2191 
2192  /* ... module not initialised or there is no UDH or smscid is NULL. */
2193  if (incoming_concat_msgs == NULL || (l = octstr_len(udh)) == 0 || smscid == NULL)
2194  return concat_none;
2195 
2196  for (pos = 1, c = -1; pos < l - 1; pos += iel + 2) {
2197  iel = octstr_get_char(udh, pos + 1);
2198  if ((c = octstr_get_char(udh, pos)) == 0 || c == 8)
2199  break;
2200  }
2201  if (pos >= l) /* no concat UDH found. */
2202  return concat_none;
2203 
2204  /* c = 0 means 8 bit, c = 8 means 16 bit concat info */
2205  sixteenbit = (c == 8);
2206  refnum = (!sixteenbit) ? octstr_get_char(udh, pos + 2) :
2207  (octstr_get_char(udh, pos + 2) << 8) | octstr_get_char(udh, pos + 3);
2208  totalparts = octstr_get_char(udh, pos + 3 + sixteenbit);
2209  part = octstr_get_char(udh, pos + 4 + sixteenbit);
2210 
2211  if (part < 1 || part > totalparts) {
2212  warning(0, "Invalid concatenation UDH [ref = %d] in message from %s!",
2213  refnum, octstr_get_cstr(msg->sms.sender));
2214  return concat_none;
2215  }
2216 
2217  /* extract UDH */
2218  udh = octstr_duplicate(msg->sms.udhdata);
2219  octstr_delete(udh, pos, iel + 2);
2220  if (octstr_len(udh) <= 1) /* no other UDH elements. */
2221  octstr_delete(udh, 0, octstr_len(udh));
2222  else
2223  octstr_set_char(udh, 0, octstr_len(udh) - 1);
2224 
2225  debug("bb.sms.splits", 0, "Got part %d [ref %d, total parts %d] of message from %s. Dump follows:",
2226  part, refnum, totalparts, octstr_get_cstr(msg->sms.sender));
2227 
2228  msg_dump(msg, 0);
2229 
2230  key = octstr_format("'%S' '%S' '%S' '%d' '%d' '%H'", msg->sms.sender, msg->sms.receiver, smscid, refnum, totalparts, udh);
2232  if ((cmsg = dict_get(incoming_concat_msgs, key)) == NULL) {
2233  cmsg = gw_malloc(sizeof(*cmsg));
2234  cmsg->refnum = refnum;
2235  cmsg->total_parts = totalparts;
2236  cmsg->udh = udh;
2237  udh = NULL;
2238  cmsg->num_parts = 0;
2239  cmsg->key = octstr_duplicate(key);
2240  cmsg->ack = ack_success;
2241  cmsg->smsc_id = octstr_duplicate(smscid);
2242  cmsg->parts = gw_malloc(totalparts * sizeof(*cmsg->parts));
2243  memset(cmsg->parts, 0, cmsg->total_parts * sizeof(*cmsg->parts)); /* clear it. */
2244 
2245  dict_put(incoming_concat_msgs, key, cmsg);
2246  }
2247  octstr_destroy(key);
2248  octstr_destroy(udh);
2249 
2250  /* check if we have seen message part before... */
2251  if (cmsg->parts[part - 1] != NULL) {
2252  error(0, "Duplicate message part %d, ref %d, from %s, to %s. Discarded!",
2253  part, refnum, octstr_get_cstr(msg->sms.sender), octstr_get_cstr(msg->sms.receiver));
2255  msg_destroy(msg);
2256  *pmsg = msg = NULL;
2258  return concat_pending;
2259  } else {
2260  cmsg->parts[part -1] = msg;
2261  cmsg->num_parts++;
2262  /* always update receive time so we have it from last part and don't timeout */
2263  cmsg->trecv = time(NULL);
2264  }
2265 
2266  if (cmsg->num_parts < cmsg->total_parts) { /* wait for more parts. */
2267  *pmsg = msg = NULL;
2269  return concat_pending;
2270  }
2271 
2272  /* we have all the parts: Put them together, modify UDH, return message. */
2273  msg = msg_duplicate(cmsg->parts[0]);
2274  uuid_generate(msg->sms.id); /* give it a new ID. */
2275 
2276  debug("bb.sms.splits",0,"Received all concatenated message parts from %s, to %s, refnum %d",
2277  octstr_get_cstr(msg->sms.sender), octstr_get_cstr(msg->sms.receiver), refnum);
2278 
2279  for (i = 1; i < cmsg->total_parts; i++)
2280  octstr_append(msg->sms.msgdata, cmsg->parts[i]->sms.msgdata);
2281 
2282  /* Attempt to save the new one, if that fails, then reply with fail. */
2283  if (store_save(msg) == -1) {
2285  msg_destroy(msg);
2286  *pmsg = msg = NULL;
2287  return concat_error;
2288  } else
2289  *pmsg = msg; /* return the message part. */
2290 
2291  /* fix up UDH */
2292  octstr_destroy(msg->sms.udhdata);
2293  msg->sms.udhdata = cmsg->udh;
2294  cmsg->udh = NULL;
2295 
2296  /* Delete it from the queue and from the Dict. */
2297  /* Note: dict_put with NULL value delete and destroy value */
2298  dict_put(incoming_concat_msgs, cmsg->key, NULL);
2300 
2301  debug("bb.sms.splits", 0, "Got full message [ref %d] of message from %s to %s. Dumping: ",
2302  refnum, octstr_get_cstr(msg->sms.sender), octstr_get_cstr(msg->sms.receiver));
2303  msg_dump(msg,0);
2304 
2305  return ret;
2306 }
2307 
Load * incoming_sms_load
Definition: smscconn_p.h:216
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
void error(int err, const char *fmt,...)
Definition: log.c:648
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:672
regex_t * re
Definition: smscconn_p.h:255
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
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:2014
void smsc2_cleanup(void)
Definition: bb_smscconn.c:1314
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:464
gw_assert(wtls_machine->packet_to_send !=NULL)
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:211
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:1109
void smscconn_shutdown(SMSCConn *conn, int finish_sending)
Definition: smscconn.c:427
void bb_smscconn_killed(void)
Definition: bb_smscconn.c:199
List * reroute_by_receiver_regex
Definition: smscconn_p.h:208
List * flow_threads
Definition: bearerbox.c:116
int smsc2_graceful_restart(Cfg *cfg)
Definition: bb_smscconn.c:1530
void octstr_append(Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:1504
static Mutex * concat_lock
Definition: bb_smscconn.c:2022
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:1930
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:1174
#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:666
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:552
static regex_t * black_list_receiver_regex
Definition: bb_smscconn.c:147
void uuid_generate(uuid_t out)
Definition: gw_uuid.c:393
List * outgoing_sms
Definition: bearerbox.c:85
static long sms_resend_retry
Definition: bb_smscconn.c:153
Octstr * id
Definition: smscconn_p.h:256
Octstr * smsc_id
Definition: bb_smscconn.c:2018
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
#define DLR_IS_SMSC_FAIL(dlr)
Definition: dlr.h:90
void octstr_append_cstr(Octstr *ostr, const char *cstr)
Definition: octstr.c:1511
Definition: msg.h:110
static Cfg * cfg
Definition: opensmppbox.c:95
void octstr_insert_data(Octstr *ostr, long pos, const char *data, long len)
Definition: octstr.c:1461
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:416
static void concat_handling_clear_old_parts(int force)
Definition: bb_smscconn.c:2078
static void handle_split(SMSCConn *conn, Msg *msg, long reason, Octstr *reply)
Definition: bb_smscconn.c:209
#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:197
Counter * incoming_dlr_counter
Definition: bearerbox.c:92
Cfg * cfg_create(Octstr *filename)
Definition: cfg.c:318
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:215
const Octstr * smscconn_admin_id(SMSCConn *conn)
Definition: smscconn.c:566
List * gwlist_search_all(List *list, void *pattern, int(*cmp)(void *, void *))
Definition: list.c:508
Counter * outgoing_dlr_counter
Definition: bearerbox.c:93
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:314
void smscconn_reconfig(SMSCConn *conn, CfgGroup *grp)
Definition: smscconn.c:763
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:283
Counter * received_dlr
Definition: smscconn_p.h:163
Definition: msg.h:79
Definition: cfg.c:164
int smscconn_status(SMSCConn *conn)
Definition: smscconn.c:724
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:209
void cfg_destroy(Cfg *cfg)
Definition: cfg.c:331
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:2021
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:2013
void octstr_delete(Octstr *ostr1, long pos, long len)
Definition: octstr.c:1527
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:732
int bb_reload_smsc_groups()
Definition: bb_smscconn.c:627
Octstr * chksum
Definition: smscconn_p.h:171
static int cmp_conn_grp_checksum(void *a, void *b)
Definition: bb_smscconn.c:734
long max_incoming_sms_qlength
Definition: bearerbox.c:98
long bb_smscconn_receive(SMSCConn *conn, Msg *sms)
Definition: bb_smscconn.c:477
int smscconn_stop(SMSCConn *conn)
Definition: smscconn.c:516
static void concat_handling_init(void)
Definition: bb_smscconn.c:2043
int reroute
Definition: smscconn_p.h:206
int route_incoming_to_boxc(Msg *msg)
Definition: bb_boxc.c:1549
const Octstr * smscconn_id(SMSCConn *conn)
Definition: smscconn.c:559
Definition: dict.c:116
#define octstr_duplicate(ostr)
Definition: octstr.h:187
List * cfg_get_multi_group(Cfg *cfg, Octstr *name)
Definition: cfg.c:645
static void concat_handling_cleanup(void)
Definition: bb_smscconn.c:2066
static void sms_router(void *arg)
Definition: bb_smscconn.c:650
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:660
Octstr * udh
Definition: bb_smscconn.c:2012
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2464
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
#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:336
#define DLR_IS_SMSC_SUCCESS(dlr)
Definition: dlr.h:89
#define DLR_SMSC_FAIL
Definition: dlr.h:76
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:1259
int load
Definition: smscconn.h:123
static Octstr * white_list_sender_url
Definition: bb_smscconn.c:136
int smscconn_send(SMSCConn *conn, Msg *msg)
Definition: smscconn.c:655
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
#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:342
int smsc2_shutdown(void)
Definition: bb_smscconn.c:1276
void dict_destroy(Dict *dict)
Definition: dict.c:215
int cfg_get_bool(int *n, CfgGroup *grp, Octstr *varname)
Definition: cfg.c:759
Definition: octstr.c:118
void bb_smscconn_sent(SMSCConn *conn, Msg *sms, Octstr *reply)
Definition: bb_smscconn.c:281
int smscconn_usable(SMSCConn *conn, Msg *msg)
Definition: smscconn.c:573
static long sms_resend_frequency
Definition: bb_smscconn.c:152
static int cmp_rout_grp_checksum(void *a, void *b)
Definition: bb_smscconn.c:751
Load * outgoing_dlr_load
Definition: smscconn_p.h:218
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
int cfg_get_integer(long *n, CfgGroup *grp, Octstr *varname)
Definition: cfg.c:742
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:2507
Load * incoming_dlr_load
Definition: smscconn_p.h:217
int smpp_pdu_init(Cfg *cfg)
Definition: smpp_pdu.c:184
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:2010
SMSCConn * smscconn_create(CfgGroup *grp, int start_as_stopped)
Definition: smscconn.c:210
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:329
struct ConcatMsg ConcatMsg
static void destroy_concatMsg(void *x)
Definition: bb_smscconn.c:2024
#define DLR_IS_FAIL(dlr)
Definition: dlr.h:87
Msg ** parts
Definition: bb_smscconn.c:2017
#define MAIN_THREAD_ID
Definition: gwthread.h:77
void smsc2_resume(int is_init)
Definition: bb_smscconn.c:1234
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:1362
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:732
static Octstr * white_list_receiver_url
Definition: bb_smscconn.c:138
CfgGroup * cfg_get_single_group(Cfg *cfg, Octstr *name)
Definition: cfg.c:639
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:2053
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:406
#define mutex_lock(m)
Definition: thread.h:130
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:415
int reroute_dlr
Definition: smscconn_p.h:210
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:2181
void smscconn_start(SMSCConn *conn)
Definition: smscconn.c:536
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:871
static long smsc2_find(Octstr *id, long start)
Definition: bb_smscconn.c:948
long smsc2_rout(Msg *msg, int resend)
Definition: bb_smscconn.c:1716
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.