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