Kannel: Open Source WAP and SMS gateway  svn-r5335
bearerbox.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  * bearerbox.c
59  *
60  * this is the core module of the bearerbox. It starts everything and
61  * listens to HTTP requests and traps signals.
62  * All started modules are responsible for the rest.
63  *
64  * Kalle Marjola <rpr@wapit.com> 2000 for project Kannel
65  */
66 
67 #include <errno.h>
68 #include <stdlib.h>
69 #include <stdio.h>
70 #include <time.h>
71 #include <string.h>
72 #include <signal.h>
73 #include <unistd.h>
74 
75 #include "gwlib/gwlib.h"
76 #include "msg.h"
77 #include "bearerbox.h"
78 #include "shared.h"
79 #include "dlr.h"
80 #include "load.h"
81 
82 /* global variables; included to other modules as needed */
83 
86 
89 
96 
97 /* incoming/outgoing sms queue control */
100 
101 
106 
107 
108 /* this is not a list of items; instead it is used as
109  * indicator to note how many threads we have.
110  * ALL flow threads must exit before we may safely change
111  * bb_status from BB_SHUTDOWN to BB_DEAD
112  *
113  * XXX: prehaps we could also have items in this list, as
114  * descriptors of each thread?
115  */
117 
118 /* and still more abuse; we use this list to put us into
119  * 'suspend' state - if there are any producers (only core adds/removes them)
120  * receiver/sender systems just sit, blocked in gwlist_consume
121  */
123 
124 /* this one is like 'suspended', but only for receiving UDP/SMSC
125  * (suspended state puts producers for both lists)
126  */
128 
129 /* configuration filename */
131 
132 volatile sig_atomic_t bb_status;
133 
134 /*
135  * Flags for main thread to check what is to do.
136  */
137 enum {
141 };
142 /* Here we will set above flags */
143 static volatile sig_atomic_t bb_todo = 0;
144 
145 /* own global variables */
146 
148 static time_t start_time;
149 volatile sig_atomic_t restart = 0;
150 
151 
152 /* to avoid copied code */
153 
154 static void set_shutdown_status(void)
155 {
156  sig_atomic_t old = bb_status;
158 
159  if (old == BB_SUSPENDED)
161  if (old == BB_SUSPENDED || old == BB_ISOLATED)
163 }
164 
165 
166 /*-------------------------------------------------------
167  * signals
168  */
169 
170 static void signal_handler(int signum)
171 {
172  /* On some implementations (i.e. linuxthreads), signals are delivered
173  * to all threads. We only want to handle each signal once for the
174  * entire box, and we let the gwthread wrapper take care of choosing
175  * one.
176  */
177  if (!gwthread_shouldhandlesignal(signum))
178  return;
179 
180  switch (signum) {
181  case SIGINT:
182  case SIGTERM:
183  if (bb_status != BB_SHUTDOWN && bb_status != BB_DEAD) {
185  }
186  else if (bb_status == BB_SHUTDOWN) {
187  bb_status = BB_DEAD;
188  }
189  else if (bb_status == BB_DEAD) {
190  panic(0, "Cannot die by its own will");
191  }
192  break;
193 
194  case SIGHUP:
196  break;
197 
198  case SIGUSR2:
200  break;
201 
202  /*
203  * It would be more proper to use SIGUSR1 for this, but on some
204  * platforms that's reserved by the pthread support.
205  */
206  case SIGQUIT:
208  break;
209  }
210 }
211 
212 static void setup_signal_handlers(void)
213 {
214  struct sigaction act;
215 
216  act.sa_handler = signal_handler;
217  sigemptyset(&act.sa_mask);
218  act.sa_flags = 0;
219  sigaction(SIGINT, &act, NULL);
220  sigaction(SIGTERM, &act, NULL);
221  sigaction(SIGQUIT, &act, NULL);
222  sigaction(SIGHUP, &act, NULL);
223  sigaction(SIGPIPE, &act, NULL);
224  sigaction(SIGUSR2, &act, NULL);
225 }
226 
227 
228 /*--------------------------------------------------------
229  * functions to start/init sub-parts of the bearerbox
230  *
231  * these functions are NOT thread safe but they have no need to be,
232  * as there is only one core bearerbox thread
233  */
234 
235 static int start_smsc(Cfg *cfg)
236 {
237  static int started = 0;
238 
239  if (started)
240  return 0;
241 
242  if (smsbox_start(cfg) == -1) {
243  error(0, "Unable to start smsbox module.");
244  return -1;
245  }
246 
247  if (smsc2_start(cfg) == -1) {
248  error(0, "Unable to start smsc module.");
249  return -1;
250  }
251 
252  started = 1;
253  return 0;
254 }
255 
256 
257 static void wdp_router(void *arg)
258 {
259  Msg *msg;
260 
262 
263  while (bb_status != BB_DEAD) {
264 
265  if ((msg = gwlist_consume(outgoing_wdp)) == NULL)
266  break;
267 
268  gw_assert(msg_type(msg) == wdp_datagram);
269 
270  /*
271  if (msg->list == sms)
272  smsc_addwdp(msg);
273  else
274  */
275 
276  udp_addwdp(msg);
277  }
278  udp_die();
279  /* smsc_endwdp(); */
280 
282 }
283 
284 
285 static int start_wap(Cfg *cfg)
286 {
287  static int started = 0;
288 
289  if (started)
290  return 0;
291 
292  wapbox_start(cfg);
293 
294  debug("bb", 0, "starting WDP router");
295  if (gwthread_create(wdp_router, NULL) == -1)
296  panic(0, "Failed to start a new thread for WDP routing");
297 
298  started = 1;
299  return 0;
300 }
301 
302 
303 static int start_udp(Cfg *cfg)
304 {
305  static int started = 0;
306 
307  if (started)
308  return 0;
309 
310  udp_start(cfg);
311 
312  start_wap(cfg);
313  started = 1;
314  return 0;
315 }
316 
317 
318 /*
319  * check that there is basic thingies in configuration
320  */
321 static int check_config(Cfg *cfg)
322 {
323  CfgGroup *grp;
324  long smsp, wapp;
325 
326  grp = cfg_get_single_group(cfg, octstr_imm("core"));
327  if (grp == NULL)
328  return -1;
329 
330  if (cfg_get_integer(&smsp, grp, octstr_imm("smsbox-port")) == -1)
331  smsp = -1;
332  if (cfg_get_integer(&wapp, grp, octstr_imm("wapbox-port")) == -1)
333  wapp = -1;
334 
335 #ifndef NO_SMS
336  grp = cfg_get_single_group(cfg, octstr_imm("smsbox"));
337  if (smsp != -1 && grp == NULL) {
338  error(0, "No 'smsbox' group in configuration, but smsbox-port set");
339  return -1;
340  }
341 #else
342  warning(0, "Kannel was compiled without SMS support");
343 #endif
344 
345 #ifndef NO_WAP
346  grp = cfg_get_single_group(cfg, octstr_imm("wapbox"));
347  if (wapp != -1 && grp == NULL) {
348  error(0, "No 'wapbox' group in configuration, but wapbox-port set");
349  return -1;
350  }
351 #else
352  warning(0, "Kannel was compiled without WAP support");
353 #endif
354 
355  return 0;
356 }
357 
358 
359 /*
360  * check our own variables
361  */
362 static int check_args(int i, int argc, char **argv)
363 {
364  if (strcmp(argv[i], "-S")==0 || strcmp(argv[i], "--suspended")==0)
366  else if (strcmp(argv[i], "-I")==0 || strcmp(argv[i], "--isolated")==0)
368  else
369  return -1;
370 
371  return 0;
372 }
373 
374 
376 {
377  CfgGroup *grp;
378  Octstr *log, *val;
379  long loglevel, store_dump_freq, value;
380  int lf, m;
381 #ifdef HAVE_LIBSSL
382  Octstr *ssl_server_cert_file;
383  Octstr *ssl_server_key_file;
384  int ssl_enabled = 0;
385 #endif /* HAVE_LIBSSL */
386  Octstr *http_proxy_host = NULL;
387  long http_proxy_port = -1;
388  int http_proxy_ssl = 0;
389  List *http_proxy_exceptions = NULL;
390  Octstr *http_proxy_username = NULL;
391  Octstr *http_proxy_password = NULL;
392  Octstr *http_proxy_exceptions_regex = NULL;
393 
394  /* defaults: use localtime and markers for access-log */
395  lf = m = 1;
396 
397  grp = cfg_get_single_group(cfg, octstr_imm("core"));
398 
399  log = cfg_get(grp, octstr_imm("log-file"));
400  if (log != NULL) {
401  if (cfg_get_integer(&loglevel, grp, octstr_imm("log-level")) == -1)
402  loglevel = 0;
403  log_open(octstr_get_cstr(log), loglevel, GW_NON_EXCL);
404  octstr_destroy(log);
405  }
406  if ((val = cfg_get(grp, octstr_imm("syslog-level"))) != NULL) {
407  long level;
408  Octstr *facility;
409  if ((facility = cfg_get(grp, octstr_imm("syslog-facility"))) != NULL) {
411  octstr_destroy(facility);
412  }
413  if (octstr_compare(val, octstr_imm("none")) == 0) {
414  log_set_syslog(NULL, 0);
415  } else if (octstr_parse_long(&level, val, 0, 10) > 0) {
416  log_set_syslog("bearerbox", level);
417  }
418  octstr_destroy(val);
419  } else {
420  log_set_syslog(NULL, 0);
421  }
422 
423  if (check_config(cfg) == -1)
424  panic(0, "Cannot start with corrupted configuration");
425 
426  /* determine which timezone we use for access logging */
427  if ((log = cfg_get(grp, octstr_imm("access-log-time"))) != NULL) {
428  lf = (octstr_case_compare(log, octstr_imm("gmt")) == 0) ? 0 : 1;
429  octstr_destroy(log);
430  }
431 
432  /* should predefined markers be used, ie. prefixing timestamp */
433  cfg_get_bool(&m, grp, octstr_imm("access-log-clean"));
434 
435  /* custom access-log format */
436  if ((log = cfg_get(grp, octstr_imm("access-log-format"))) != NULL) {
437  bb_alog_init(log);
438  octstr_destroy(log);
439  }
440 
441  /* open access-log file */
442  if ((log = cfg_get(grp, octstr_imm("access-log"))) != NULL) {
443  alog_open(octstr_get_cstr(log), lf, m ? 0 : 1);
444  octstr_destroy(log);
445  }
446 
447  if (cfg_get_integer(&store_dump_freq, grp,
448  octstr_imm("store-dump-freq")) == -1)
449  store_dump_freq = -1;
450 
451  log = cfg_get(grp, octstr_imm("store-file"));
452  /* initialize the store file */
453  if (log != NULL) {
454  warning(0, "'store-file' option deprecated, please use 'store-location' and 'store-type' instead.");
455  val = octstr_create("file");
456  } else {
457  log = cfg_get(grp, octstr_imm("store-location"));
458  val = cfg_get(grp, octstr_imm("store-type"));
459  }
460  if (store_init(cfg, val, log, store_dump_freq, msg_pack, msg_unpack_wrapper) == -1)
461  panic(0, "Could not start with store init failed.");
462  octstr_destroy(val);
463  octstr_destroy(log);
464 
465  cfg_get_integer(&http_proxy_port, grp, octstr_imm("http-proxy-port"));
466 #ifdef HAVE_LIBSSL
467  cfg_get_bool(&http_proxy_ssl, grp, octstr_imm("http-proxy-ssl"));
468 #endif /* HAVE_LIBSSL */
469 
470  http_proxy_host = cfg_get(grp,
471  octstr_imm("http-proxy-host"));
472  http_proxy_username = cfg_get(grp,
473  octstr_imm("http-proxy-username"));
474  http_proxy_password = cfg_get(grp,
475  octstr_imm("http-proxy-password"));
476  http_proxy_exceptions = cfg_get_list(grp,
477  octstr_imm("http-proxy-exceptions"));
478  http_proxy_exceptions_regex = cfg_get(grp,
479  octstr_imm("http-proxy-exceptions-regex"));
480 
481  conn_config_ssl (grp);
482 
483  /*
484  * Make sure we have "ssl-server-cert-file" and "ssl-server-key-file" specified
485  * in the core group since we need it to run SSL-enabled internal box
486  * connections configured via "smsbox-port-ssl = yes" and "wapbox-port-ssl = yes".
487  * Check only these, because for "admin-port-ssl" and "sendsms-port-ssl" for the
488  * SSL-enabled HTTP servers are probed within gw/bb_http.c:httpadmin_start()
489  */
490 #ifdef HAVE_LIBSSL
491  ssl_server_cert_file = cfg_get(grp, octstr_imm("ssl-server-cert-file"));
492  ssl_server_key_file = cfg_get(grp, octstr_imm("ssl-server-key-file"));
493  if (ssl_server_cert_file != NULL && ssl_server_key_file != NULL) {
494  /* we are fine, at least files are specified in the configuration */
495  } else {
496  cfg_get_bool(&ssl_enabled, grp, octstr_imm("smsbox-port-ssl"));
497  cfg_get_bool(&ssl_enabled, grp, octstr_imm("wapbox-port-ssl"));
498  if (ssl_enabled) {
499  panic(0, "You MUST specify cert and key files within core group for SSL-enabled inter-box connections!");
500  }
501  }
502  octstr_destroy(ssl_server_cert_file);
503  octstr_destroy(ssl_server_key_file);
504 #endif /* HAVE_LIBSSL */
505 
506  /* if all seems to be OK by the first glimpse, real start-up */
507 
512 
519 
521 
523  /* add 60,300,-1 entries */
528  /* add 60,300,-1 entries */
533  /* add 60,300,-1 entries to dlr */
538  /* add 60,300,-1 entries to dlr */
542 
544 
545  /* http-admin is REQUIRED */
547 
549  octstr_imm("maximum-queue-length")) == -1)
551  else {
552  warning(0, "Option 'maximum-queue-length' is deprecated! Please use"
553  " 'sms-incoming-queue-limit' instead!");
554  }
555 
556  if (max_incoming_sms_qlength == -1 &&
558  octstr_imm("sms-incoming-queue-limit")) == -1)
560 
562  octstr_imm("sms-outgoing-queue-limit")) == -1)
564 
565  if (max_outgoing_sms_qlength < 0)
567 
568  if (cfg_get_integer(&value, grp, octstr_imm("http-timeout")) == 0)
570 #ifndef NO_SMS
571  {
572  List *list;
573 
574  list = cfg_get_multi_group(cfg, octstr_imm("smsc"));
575  if (list != NULL) {
576  gwlist_destroy(list, NULL);
577  if (start_smsc(cfg) == -1) {
578  panic(0, "Unable to start SMSCs.");
579  return NULL;
580  }
581  }
582  }
583 #endif
584 
585 #ifndef NO_WAP
586  grp = cfg_get_single_group(cfg, octstr_imm("core"));
587  val = cfg_get(grp, octstr_imm("wdp-interface-name"));
588  if (val != NULL && octstr_len(val) > 0)
589  start_udp(cfg);
590  octstr_destroy(val);
591 
592  if (cfg_get_single_group(cfg, octstr_imm("wapbox")) != NULL)
593  start_wap(cfg);
594 #endif
595 
596  if (http_proxy_host != NULL && http_proxy_port > 0) {
597  http_use_proxy(http_proxy_host, http_proxy_port, http_proxy_ssl,
598  http_proxy_exceptions, http_proxy_username,
599  http_proxy_password, http_proxy_exceptions_regex);
600  }
601 
602  octstr_destroy(http_proxy_host);
603  octstr_destroy(http_proxy_username);
604  octstr_destroy(http_proxy_password);
605  octstr_destroy(http_proxy_exceptions_regex);
606  gwlist_destroy(http_proxy_exceptions, octstr_destroy_item);
607 
608  return cfg;
609 }
610 
611 
612 static void empty_msg_lists(void)
613 {
614  Msg *msg;
615 
616 #ifndef NO_WAP
618  warning(0, "Remaining WDP: %ld incoming, %ld outgoing",
620 
621  info(0, "Total WDP messages: received %ld, sent %ld",
624 #endif
625 
626  while ((msg = gwlist_extract_first(incoming_wdp)) != NULL)
627  msg_destroy(msg);
628  while ((msg = gwlist_extract_first(outgoing_wdp)) != NULL)
629  msg_destroy(msg);
630 
633 
636 
637 #ifndef NO_SMS
638  /* XXX we should record these so that they are not forever lost... */
640  debug("bb", 0, "Remaining SMS: %ld incoming, %ld outgoing",
642 
643  info(0, "Total SMS messages: received %ld, dlr %ld, sent %ld, dlr %ld",
648 #endif
649 
652 
657 
662 }
663 
664 
666 {
667  char id[UUID_STR_LEN + 1];
668 
669  gw_assert(msg != NULL),
670  gw_assert(msg_type(msg) == sms);
671 
672  switch (msg->sms.sms_type) {
673  case mt_push:
674  case mt_reply:
675  case report_mt:
677  break;
678  case mo:
679  case report_mo:
681  break;
682  default:
683  uuid_unparse(msg->sms.id, id);
684  error(0, "Not handled sms_type %ld within store for message ID %s",
685  msg->sms.sms_type, id);
686  msg_destroy(msg);
687  break;
688  }
689 }
690 
691 
692 int main(int argc, char **argv)
693 {
694  int cf_index;
695  Cfg *cfg;
696 
698 
699  gwlib_init();
700  start_time = time(NULL);
701 
706 
707  cf_index = get_and_set_debugs(argc, argv, check_args);
708 
709  if (argv[cf_index] == NULL)
710  cfg_filename = octstr_create("kannel.conf");
711  else
712  cfg_filename = octstr_create(argv[cf_index]);
714 
715  if (cfg_read(cfg) == -1)
716  panic(0, "Couldn't read configuration from `%s'.", octstr_get_cstr(cfg_filename));
717 
718  dlr_init(cfg);
719 
720  report_versions("bearerbox");
721 
723 
724  if (init_bearerbox(cfg) == NULL)
725  panic(0, "Initialization failed.");
726 
727  info(0, "----------------------------------------");
728  info(0, GW_NAME " bearerbox II version %s starting", GW_VERSION);
729 
730  gwthread_sleep(5.0); /* give time to threads to register themselves */
731 
732  if (store_load(dispatch_into_queue) == -1)
733  panic(0, "Cannot start with store-file failing");
734 
735  info(0, "MAIN: Start-up done, entering mainloop");
736  if (bb_status == BB_SUSPENDED) {
737  info(0, "Gateway is now SUSPENDED by startup arguments");
738  } else if (bb_status == BB_ISOLATED) {
739  info(0, "Gateway is now ISOLATED by startup arguments");
741  } else {
742  smsc2_resume(1);
745  }
746 
747  while (bb_status != BB_SHUTDOWN && bb_status != BB_DEAD &&
749  /* debug("bb", 0, "Main Thread: going to sleep."); */
750  /*
751  * Not infinite sleep here, because we should notice
752  * when all "flow threads" are dead and shutting bearerbox
753  * down.
754  * XXX if all "flow threads" call gwthread_wakeup(MAIN_THREAD_ID),
755  * we can enter infinite sleep then.
756  */
757  gwthread_sleep(10.0);
758  /* debug("bb", 0, "Main Thread: woken up."); */
759 
760  if (bb_todo == 0) {
761  continue;
762  }
763 
765  warning(0, "SIGHUP received, re-opening logs and gracefully restarting.");
766  log_reopen();
767  alog_reopen();
770  }
771 
772  if (bb_todo & BB_LOGREOPEN) {
773  warning(0, "SIGUSR2 received, re-opening logs.");
774  log_reopen();
775  alog_reopen();
777  }
778 
779  if (bb_todo & BB_CHECKLEAKS) {
780  warning(0, "SIGQUIT received, reporting memory usage.");
781  gw_check_leaks();
783  }
784  }
785 
786  if (bb_status == BB_SHUTDOWN || bb_status == BB_DEAD)
787  warning(0, "Killing signal or HTTP admin command received, shutting down...");
788 
789  /* call shutdown */
790  bb_shutdown();
791 
792  /* wake up any sleeping threads */
794 
795  /* wait until flow threads exit */
796  while (gwlist_consume(flow_threads) != NULL)
797  ;
798 
799  info(0, "All flow threads have died, killing core");
800  bb_status = BB_DEAD;
801  httpadmin_stop();
802 
803  boxc_cleanup();
804  smsc2_cleanup();
805  store_shutdown();
806  empty_msg_lists();
808  gwlist_destroy(suspended, NULL);
809  gwlist_destroy(isolated, NULL);
811 
812  alog_close(); /* if we have any */
814  cfg_destroy(cfg);
816  dlr_shutdown();
817 
818  /* now really restart */
819  if (restart)
820  restart_box(argv);
821 
822  gwlib_shutdown();
823 
824  return 0;
825 }
826 
827 
828 /*----------------------------------------------------------------
829  * public functions used via HTTP adminstration interface/module
830  */
831 
832 int bb_shutdown(void)
833 {
834  static int called = 0;
835 
837 
838  if (called) {
840  return -1;
841  }
842  debug("bb", 0, "Shutting down " GW_NAME "...");
843 
844  called = 1;
847 
848 #ifndef NO_SMS
849  debug("bb", 0, "shutting down smsc");
850  smsc2_shutdown();
851 #endif
852 #ifndef NO_WAP
853  debug("bb", 0, "shutting down udp");
854  udp_shutdown();
855 #endif
856 
857  return 0;
858 }
859 
860 
861 int bb_isolate(void)
862 {
866  return -1;
867  }
868  if (bb_status == BB_RUNNING) {
869  smsc2_suspend();
871  } else
873 
876  return 0;
877 }
878 
879 
880 int bb_suspend(void)
881 {
883  if (bb_status != BB_RUNNING && bb_status != BB_ISOLATED) {
885  return -1;
886  }
887  if (bb_status != BB_ISOLATED) {
888  smsc2_suspend();
890  }
894  return 0;
895 }
896 
897 
898 int bb_resume(void)
899 {
903  return -1;
904  }
905  if (bb_status == BB_SUSPENDED)
907 
908  smsc2_resume(0);
912  return 0;
913 }
914 
915 
916 int bb_flush_dlr(void)
917 {
918  /* beware that mutex locking is done in dlr_foobar() routines */
919  if (bb_status != BB_SUSPENDED) {
920  return -1;
921  }
922  dlr_flush();
923  return 0;
924 }
925 
926 
928 {
929  return smsc2_stop_smsc(id);
930 }
931 
932 
934 {
935  return smsc2_restart_smsc(id);
936 }
937 
939 {
940  return smsc2_add_smsc(id);
941 }
942 
944 {
945  return smsc2_remove_smsc(id);
946 }
947 
948 int bb_restart(void)
949 {
950  restart = 1;
951  return bb_shutdown();
952 }
953 
955 {
956  Cfg *cfg;
957 
958  info(0, "Reloading configuration resource `%s'.", octstr_get_cstr(cfg_filename));
960  if (cfg_read(cfg) == -1) {
961  error(0, "Error processing configuration resource `%s'. Continue with existing configuration.",
963  return -1;
964  }
965 
968  return 0;
969 }
970 
972 {
973  return smsc2_reload_lists();
974 }
975 
976 int bb_remove_message(Octstr *message_id)
977 {
978  Msg *msg;
979  int ret;
980 
981  msg = msg_create(ack);
982  msg->ack.nack = ack_failed;
983  msg->ack.time = time(NULL);
984  uuid_parse(octstr_get_cstr(message_id), msg->ack.id);
985  ret = store_save(msg);
986  msg_destroy(msg);
987  if (ret != 0) {
988  error(0, "Could not delete message %s", octstr_get_cstr(message_id));
989  return -1;
990  }
991  return 0;
992 }
993 
994 
995 #define append_status(r, s, f, x) { s = f(x); octstr_append(r, s); \
996  octstr_destroy(s); }
997 
998 Octstr *bb_print_status(int status_type)
999 {
1000  char *s, *lb;
1001  char *frmt, *footer;
1002  Octstr *ret, *str, *version;
1003  time_t t;
1004 
1005  if ((lb = bb_status_linebreak(status_type)) == NULL)
1006  return octstr_create("Un-supported format");
1007 
1008  t = time(NULL) - start_time;
1009 
1010  if (bb_status == BB_RUNNING)
1011  s = "running";
1012  else if (bb_status == BB_ISOLATED)
1013  s = "isolated";
1014  else if (bb_status == BB_SUSPENDED)
1015  s = "suspended";
1016  else if (bb_status == BB_FULL)
1017  s = "filled";
1018  else
1019  s = "going down";
1020 
1021  version = version_report_string("bearerbox");
1022 
1023  if (status_type == BBSTATUS_HTML) {
1024  frmt = "%s</p>\n\n"
1025  " <p>Status: %s, uptime %ldd %ldh %ldm %lds</p>\n\n"
1026  " <p>WDP: received %ld (%ld queued), sent %ld "
1027  "(%ld queued)</p>\n\n"
1028  " <p>SMS: received %ld (%ld queued), sent %ld "
1029  "(%ld queued), store size %ld<br>\n"
1030  " SMS: inbound (%.2f,%.2f,%.2f) msg/sec, "
1031  "outbound (%.2f,%.2f,%.2f) msg/sec</p>\n\n"
1032  " <p>DLR: received %ld, sent %ld<br>\n"
1033  " DLR: inbound (%.2f,%.2f,%.2f) msg/sec, outbound (%.2f,%.2f,%.2f) msg/sec<br>\n"
1034  " DLR: %ld queued, using %s storage</p>\n\n";
1035  footer = "<p>";
1036  } else if (status_type == BBSTATUS_WML) {
1037  frmt = "%s</p>\n\n"
1038  " <p>Status: %s, uptime %ldd %ldh %ldm %lds</p>\n\n"
1039  " <p>WDP: received %ld (%ld queued)<br/>\n"
1040  " WDP: sent %ld (%ld queued)</p>\n\n"
1041  " <p>SMS: received %ld (%ld queued)<br/>\n"
1042  " SMS: sent %ld (%ld queued)<br/>\n"
1043  " SMS: store size %ld<br/>\n"
1044  " SMS: inbound (%.2f,%.2f,%.2f) msg/sec<br/>\n"
1045  " SMS: outbound (%.2f,%.2f,%.2f) msg/sec</p>\n"
1046  " <p>DLR: received %ld<br/>\n"
1047  " DLR: sent %ld<br/>\n"
1048  " DLR: inbound (%.2f,%.2f,%.2f) msg/sec<br/>\n"
1049  " DLR: outbound (%.2f,%.2f,%.2f) msg/sec<br/>\n"
1050  " DLR: %ld queued<br/>\n"
1051  " DLR: using %s storage</p>\n\n";
1052  footer = "<p>";
1053  } else if (status_type == BBSTATUS_XML) {
1054  frmt = "<version>%s</version>\n"
1055  "<status>%s, uptime %ldd %ldh %ldm %lds</status>\n"
1056  "\t<wdp>\n\t\t<received><total>%ld</total><queued>%ld</queued>"
1057  "</received>\n\t\t<sent><total>%ld</total><queued>%ld</queued>"
1058  "</sent>\n\t</wdp>\n"
1059  "\t<sms>\n\t\t<received><total>%ld</total><queued>%ld</queued>"
1060  "</received>\n\t\t<sent><total>%ld</total><queued>%ld</queued>"
1061  "</sent>\n\t\t<storesize>%ld</storesize>\n\t\t"
1062  "<inbound>%.2f,%.2f,%.2f</inbound>\n\t\t"
1063  "<outbound>%.2f,%.2f,%.2f</outbound>\n\t\t"
1064  "</sms>\n"
1065  "\t<dlr>\n\t\t<received><total>%ld</total></received>\n\t\t"
1066  "<sent><total>%ld</total></sent>\n\t\t"
1067  "<inbound>%.2f,%.2f,%.2f</inbound>\n\t\t"
1068  "<outbound>%.2f,%.2f,%.2f</outbound>\n\t\t"
1069  "<queued>%ld</queued>\n\t\t<storage>%s</storage>\n\t</dlr>\n";
1070  footer = "";
1071  } else {
1072  frmt = "%s\n\nStatus: %s, uptime %ldd %ldh %ldm %lds\n\n"
1073  "WDP: received %ld (%ld queued), sent %ld (%ld queued)\n\n"
1074  "SMS: received %ld (%ld queued), sent %ld (%ld queued), store size %ld\n"
1075  "SMS: inbound (%.2f,%.2f,%.2f) msg/sec, "
1076  "outbound (%.2f,%.2f,%.2f) msg/sec\n\n"
1077  "DLR: received %ld, sent %ld\n"
1078  "DLR: inbound (%.2f,%.2f,%.2f) msg/sec, outbound (%.2f,%.2f,%.2f) msg/sec\n"
1079  "DLR: %ld queued, using %s storage\n\n";
1080  footer = "";
1081  }
1082 
1083  ret = octstr_format(frmt,
1084  octstr_get_cstr(version),
1085  s, t/3600/24, t/3600%24, t/60%60, t%60,
1091  store_messages(),
1097  dlr_messages(), dlr_type());
1098 
1099  octstr_destroy(version);
1100 
1101  append_status(ret, str, boxc_status, status_type);
1102  append_status(ret, str, smsc2_status, status_type);
1103  octstr_append_cstr(ret, footer);
1104 
1105  return ret;
1106 }
1107 
1108 
1109 char *bb_status_linebreak(int status_type)
1110 {
1111  switch (status_type) {
1112  case BBSTATUS_HTML:
1113  return "<br>\n";
1114  case BBSTATUS_WML:
1115  return "<br/>\n";
1116  case BBSTATUS_TEXT:
1117  return "\n";
1118  case BBSTATUS_XML:
1119  return "\n";
1120  default:
1121  return NULL;
1122  }
1123 }
volatile sig_atomic_t bb_status
Definition: bearerbox.c:132
Counter * incoming_dlr_counter
Definition: bearerbox.c:92
static void wdp_router(void *arg)
Definition: bearerbox.c:257
void error(int err, const char *fmt,...)
Definition: log.c:648
int httpadmin_start(Cfg *cfg)
Definition: bb_http.c:557
void info(int err, const char *fmt,...)
Definition: log.c:672
int boxc_incoming_wdp_queue(void)
Definition: bb_boxc.c:1510
static int start_wap(Cfg *cfg)
Definition: bearerbox.c:285
int smsc2_add_smsc(Octstr *id)
Definition: bb_smscconn.c:1112
static void dispatch_into_queue(Msg *msg)
Definition: bearerbox.c:665
Counter * incoming_wdp_counter
Definition: bearerbox.c:94
List * suspended
Definition: bearerbox.c:122
List * outgoing_sms
Definition: bearerbox.c:85
void smsc2_cleanup(void)
Definition: bb_smscconn.c:1314
static void set_shutdown_status(void)
Definition: bearerbox.c:154
Load * outgoing_sms_load
Definition: bearerbox.c:102
gw_assert(wtls_machine->packet_to_send !=NULL)
Definition: msg.h:106
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 smsc2_restart_smsc(Octstr *id)
Definition: bb_smscconn.c:998
Load * incoming_sms_load
Definition: bearerbox.c:103
char * bb_status_linebreak(int status_type)
Definition: bearerbox.c:1109
static int check_config(Cfg *cfg)
Definition: bearerbox.c:321
int udp_addwdp(Msg *msg)
Definition: bb_udp.c:385
int smsc2_graceful_restart(Cfg *cfg)
Definition: bb_smscconn.c:1530
Definition: msg.h:109
List * cfg_get_list(CfgGroup *grp, Octstr *varname)
Definition: cfg.c:790
void log_reopen(void)
Definition: log.c:297
static void empty_msg_lists(void)
Definition: bearerbox.c:612
static int check_args(int i, int argc, char **argv)
Definition: bearerbox.c:362
long gwlist_len(List *list)
Definition: list.c:166
int restart_box(char **argv)
Definition: shared.c:279
int smsc2_reload_lists(void)
Definition: bb_smscconn.c:1174
#define mutex_create()
Definition: thread.h:96
long(* store_messages)(void)
Definition: bb_store.c:71
List * incoming_wdp
Definition: bearerbox.c:87
Msg * msg_unpack_wrapper(Octstr *os)
Definition: msg.c:256
int load_add_interval(Load *load, int interval)
Definition: load.c:111
msg_type
Definition: msg.h:73
#define cfg_get(grp, varname)
Definition: cfg.h:86
static Mutex * status_mutex
Definition: bearerbox.c:147
void uuid_unparse(const uuid_t uu, char *out)
Definition: gw_uuid.c:562
static volatile sig_atomic_t bb_todo
Definition: bearerbox.c:143
#define msg_create(type)
Definition: msg.h:136
int gwthread_shouldhandlesignal(int signal)
void octstr_append_cstr(Octstr *ostr, const char *cstr)
Definition: octstr.c:1511
Definition: msg.h:110
static Cfg * cfg
Definition: opensmppbox.c:95
double load_get(Load *load, int pos)
Definition: load.c:191
int bb_add_smsc(Octstr *id)
Definition: bearerbox.c:938
int udp_outgoing_queue(void)
Definition: bb_udp.c:460
int bb_restart_smsc(Octstr *id)
Definition: bearerbox.c:933
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
void bb_alog_init(const Octstr *format)
Definition: bb_alog.c:359
static time_t start_time
Definition: bearerbox.c:148
Cfg * cfg_create(Octstr *filename)
Definition: cfg.c:318
int cfg_read(Cfg *cfg)
Definition: cfg.c:452
int smsc2_remove_smsc(Octstr *id)
Definition: bb_smscconn.c:1083
List * isolated
Definition: bearerbox.c:127
Definition: msg.h:108
int uuid_parse(const char *in, uuid_t uu)
Definition: gw_uuid.c:476
void msg_destroy_item(void *msg)
Definition: msg.c:147
void bb_alog_shutdown(void)
Definition: bb_alog.c:367
int bb_remove_smsc(Octstr *id)
Definition: bearerbox.c:943
long max_outgoing_sms_qlength
Definition: bearerbox.c:99
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:283
int udp_die(void)
Definition: bb_udp.c:434
#define DEFAULT_OUTGOING_SMS_QLENGTH
Definition: bearerbox.h:69
int bb_flush_dlr(void)
Definition: bearerbox.c:916
Definition: msg.h:79
Definition: cfg.c:164
Counter * counter_create(void)
Definition: counter.c:94
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
Load * incoming_dlr_load
Definition: bearerbox.c:104
void conn_config_ssl(CfgGroup *grp)
Definition: conn.c:1546
void gwlist_remove_producer(List *list)
Definition: list.c:401
void httpadmin_stop(void)
Definition: bb_http.c:618
static void signal_handler(int signum)
Definition: bearerbox.c:170
long max_incoming_sms_qlength
Definition: bearerbox.c:98
List * incoming_sms
Definition: bearerbox.c:84
const char * dlr_type(void)
Definition: dlr.c:319
int store_init(Cfg *cfg, const Octstr *type, const Octstr *fname, long dump_freq, void *pack_func, void *unpack_func)
Definition: bb_store.c:82
int bb_suspend(void)
Definition: bearerbox.c:880
int bb_reload_lists(void)
Definition: bearerbox.c:971
List * cfg_get_multi_group(Cfg *cfg, Octstr *name)
Definition: cfg.c:645
Counter * outgoing_sms_counter
Definition: bearerbox.c:91
int smsbox_start(Cfg *cfg)
Definition: bb_boxc.c:1250
int bb_stop_smsc(Octstr *id)
Definition: bearerbox.c:927
void msg_destroy(Msg *msg)
Definition: msg.c:132
static int start_smsc(Cfg *cfg)
Definition: bearerbox.c:235
int octstr_case_compare(const Octstr *os1, const Octstr *os2)
Definition: octstr.c:903
Load * outgoing_dlr_load
Definition: bearerbox.c:105
int main(int argc, char **argv)
Definition: bearerbox.c:692
void warning(int err, const char *fmt,...)
Definition: log.c:660
int udp_start(Cfg *cfg)
Definition: bb_udp.c:323
void log_set_syslog_facility(char *facility)
Definition: log.c:278
void alog_open(char *fname, int use_localtm, int use_markers)
Definition: accesslog.c:129
int bb_graceful_restart(void)
Definition: bearerbox.c:954
int udp_shutdown(void)
Definition: bb_udp.c:424
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2464
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
volatile sig_atomic_t restart
Definition: bearerbox.c:149
Counter * incoming_sms_counter
Definition: bearerbox.c:90
#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
unsigned long counter_value(Counter *counter)
Definition: counter.c:145
#define load_create()
Definition: load.h:78
void gwthread_sleep(double seconds)
void log_set_syslog(const char *ident, int syslog_level)
Definition: log.c:284
void mutex_destroy(Mutex *mutex)
Definition: thread.c:97
void smsc2_suspend(void)
Definition: bb_smscconn.c:1259
Counter * outgoing_dlr_counter
Definition: bearerbox.c:93
int smsbox_restart(Cfg *cfg)
Definition: bb_boxc.c:1316
#define UUID_STR_LEN
Definition: gw_uuid.h:19
void boxc_cleanup(void)
Definition: bb_boxc.c:1527
void alog_reopen(void)
Definition: accesslog.c:85
void(* store_shutdown)(void)
Definition: bb_store.c:76
void report_versions(const char *boxname)
Definition: utils.c:539
int log_open(char *filename, int level, enum excl_state excl)
Definition: log.c:375
long octstr_len(const Octstr *ostr)
Definition: octstr.c:342
int smsc2_shutdown(void)
Definition: bb_smscconn.c:1276
#define append_status(r, s, f, x)
Definition: bearerbox.c:995
void dlr_init(Cfg *cfg)
Definition: dlr.c:233
int cfg_get_bool(int *n, CfgGroup *grp, Octstr *varname)
Definition: cfg.c:759
Definition: octstr.c:118
int bb_shutdown(void)
Definition: bearerbox.c:832
void * gwlist_consume(List *list)
Definition: list.c:427
int bb_resume(void)
Definition: bearerbox.c:898
Octstr * cfg_filename
Definition: bearerbox.c:130
void http_use_proxy(Octstr *hostname, int port, int ssl, List *exceptions, Octstr *username, Octstr *password, Octstr *exceptions_regex)
Definition: http.c:268
void dlr_flush(void)
Definition: dlr.c:491
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
static void setup_signal_handlers(void)
Definition: bearerbox.c:212
int wapbox_start(Cfg *cfg)
Definition: bb_boxc.c:1339
#define panic
Definition: log.h:87
Definition: cfg.c:73
int(* store_load)(void(*receive_msg)(Msg *))
Definition: bb_store.c:74
void load_destroy(Load *load)
Definition: load.c:145
Definition: load.c:76
List * flow_threads
Definition: bearerbox.c:116
long octstr_parse_long(long *nump, Octstr *ostr, long pos, int base)
Definition: octstr.c:749
void alog_close(void)
Definition: accesslog.c:111
void gwlib_shutdown(void)
Definition: gwlib.c:94
Octstr * msg_pack(Msg *msg)
Definition: msg.c:181
#define gwlist_create()
Definition: list.h:136
List * outgoing_wdp
Definition: bearerbox.c:88
int bb_remove_message(Octstr *message_id)
Definition: bearerbox.c:976
Octstr * boxc_status(int status_type)
Definition: bb_boxc.c:1386
Counter * outgoing_wdp_counter
Definition: bearerbox.c:95
int(* store_save)(Msg *msg)
Definition: bb_store.c:72
Definition: thread.h:76
Octstr * version_report_string(const char *boxname)
Definition: utils.c:549
void gwlib_init(void)
Definition: gwlib.c:78
Definition: msg.h:107
void smsc2_resume(int is_init)
Definition: bb_smscconn.c:1234
Octstr * smsc2_status(int status_type)
Definition: bb_smscconn.c:1362
CfgGroup * cfg_get_single_group(Cfg *cfg, Octstr *name)
Definition: cfg.c:639
void gwlist_add_producer(List *list)
Definition: list.c:383
long dlr_messages(void)
Definition: dlr.c:308
int smsc2_start(Cfg *cfg)
Definition: bb_smscconn.c:806
int bb_isolate(void)
Definition: bearerbox.c:861
void http_set_client_timeout(long timeout)
Definition: http.c:1751
int bb_restart(void)
Definition: bearerbox.c:948
#define mutex_lock(m)
Definition: thread.h:130
int get_and_set_debugs(int argc, char **argv, int(*find_own)(int index, int argc, char **argv))
Definition: utils.c:626
void gwthread_wakeup_all(void)
Definition: list.c:102
static Octstr * lf
Definition: smsc_smasi.c:222
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
void dlr_shutdown()
Definition: dlr.c:299
static int start_udp(Cfg *cfg)
Definition: bearerbox.c:303
static Cfg * init_bearerbox(Cfg *cfg)
Definition: bearerbox.c:375
Octstr * bb_print_status(int status_type)
Definition: bearerbox.c:998
int gwlist_producer_count(List *list)
Definition: list.c:391
int octstr_compare(const Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:871
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.