static void run_wapbox(void *arg) { Boxc *newconn; List *newlist; long sender; gwlist_add_producer(flow_threads); newconn = arg; newconn->is_wap = 1; /* * create a new incoming list for just that box, * and add it to list of list pointers, so we can start * to route messages to it. */ debug("bb", 0, "setting up systems for new wapbox"); newlist = gwlist_create(); /* this is released by the sender/receiver if it exits */ gwlist_add_producer(newlist); newconn->incoming = newlist; newconn->retry = incoming_wdp; newconn->outgoing = outgoing_wdp; sender = gwthread_create(boxc_sender, newconn); if (sender == -1) { error(0, "Failed to start a new thread, disconnecting client <%s>", octstr_get_cstr(newconn->client_ip)); goto cleanup; } gwlist_append(wapbox_list, newconn); gwlist_add_producer(newconn->outgoing); boxc_receiver(newconn); /* cleanup after receiver has exited */ gwlist_remove_producer(newconn->outgoing); gwlist_lock(wapbox_list); gwlist_delete_equal(wapbox_list, newconn); gwlist_unlock(wapbox_list); while (gwlist_producer_count(newlist) > 0) gwlist_remove_producer(newlist); newconn->alive = 0; gwthread_join(sender); cleanup: gw_assert(gwlist_len(newlist) == 0); gwlist_destroy(newlist, NULL); boxc_destroy(newconn); gwlist_remove_producer(flow_threads); }
int gw_rwlock_wrlock(RWLock *lock) { int ret = 0; gw_assert(lock != NULL); #ifdef HAVE_PTHREAD_RWLOCK ret = pthread_rwlock_wrlock(&lock->rwlock); if (ret != 0) panic(ret, "Error while pthread_rwlock_wrlock."); #else RWDEBUG("", 0, "------------ gw_rwlock_wrlock(%p) ----------", lock); gwlist_lock(lock->rwlock); RWDEBUG("", 0, "------------ gw_rwlock_wrlock(%p) producers=%d", lock, gwlist_producer_count(lock->rwlock)); /* wait for reader */ gwlist_consume(lock->rwlock); lock->writer = gwthread_self(); #endif return ret; }
int main(int argc, char **argv) { int cf_index; Cfg *cfg; bb_status = BB_RUNNING; gwlib_init(); start_time = time(NULL); suspended = gwlist_create(); isolated = gwlist_create(); gwlist_add_producer(suspended); gwlist_add_producer(isolated); cf_index = get_and_set_debugs(argc, argv, check_args); if (argv[cf_index] == NULL) cfg_filename = octstr_create("kannel.conf"); else cfg_filename = octstr_create(argv[cf_index]); cfg = cfg_create(cfg_filename); if (cfg_read(cfg) == -1) panic(0, "Couldn't read configuration from `%s'.", octstr_get_cstr(cfg_filename)); dlr_init(cfg); report_versions("bearerbox"); flow_threads = gwlist_create(); if (init_bearerbox(cfg) == NULL) panic(0, "Initialization failed."); info(0, "----------------------------------------"); info(0, GW_NAME " bearerbox II version %s starting", GW_VERSION); gwthread_sleep(5.0); /* give time to threads to register themselves */ if (store_load(dispatch_into_queue) == -1) panic(0, "Cannot start with store-file failing"); info(0, "MAIN: Start-up done, entering mainloop"); if (bb_status == BB_SUSPENDED) { info(0, "Gateway is now SUSPENDED by startup arguments"); } else if (bb_status == BB_ISOLATED) { info(0, "Gateway is now ISOLATED by startup arguments"); gwlist_remove_producer(suspended); } else { smsc2_resume(1); gwlist_remove_producer(suspended); gwlist_remove_producer(isolated); } while (bb_status != BB_SHUTDOWN && bb_status != BB_DEAD && gwlist_producer_count(flow_threads) > 0) { /* debug("bb", 0, "Main Thread: going to sleep."); */ /* * Not infinite sleep here, because we should notice * when all "flow threads" are dead and shutting bearerbox * down. * XXX if all "flow threads" call gwthread_wakeup(MAIN_THREAD_ID), * we can enter infinite sleep then. */ gwthread_sleep(10.0); /* debug("bb", 0, "Main Thread: woken up."); */ if (bb_todo == 0) { continue; } if (bb_todo & BB_LOGREOPEN) { warning(0, "SIGHUP received, catching and re-opening logs"); log_reopen(); alog_reopen(); bb_todo = bb_todo & ~BB_LOGREOPEN; } if (bb_todo & BB_CHECKLEAKS) { warning(0, "SIGQUIT received, reporting memory usage."); gw_check_leaks(); bb_todo = bb_todo & ~BB_CHECKLEAKS; } } if (bb_status == BB_SHUTDOWN || bb_status == BB_DEAD) warning(0, "Killing signal or HTTP admin command received, shutting down..."); /* call shutdown */ bb_shutdown(); /* wait until flow threads exit */ while (gwlist_consume(flow_threads) != NULL) ; info(0, "All flow threads have died, killing core"); bb_status = BB_DEAD; httpadmin_stop(); boxc_cleanup(); smsc2_cleanup(); store_shutdown(); empty_msg_lists(); gwlist_destroy(flow_threads, NULL); gwlist_destroy(suspended, NULL); gwlist_destroy(isolated, NULL); mutex_destroy(status_mutex); alog_close(); /* if we have any */ bb_alog_shutdown(); cfg_destroy(cfg); octstr_destroy(cfg_filename); dlr_shutdown(); /* now really restart */ if (restart) restart_box(argv); gwlib_shutdown(); return 0; }
static void run_smsbox(void *arg) { Boxc *newconn; long sender; Msg *msg; List *keys; Octstr *key; gwlist_add_producer(flow_threads); newconn = arg; newconn->incoming = gwlist_create(); gwlist_add_producer(newconn->incoming); newconn->retry = incoming_sms; newconn->outgoing = outgoing_sms; newconn->sent = dict_create(smsbox_max_pending, NULL); newconn->pending = semaphore_create(smsbox_max_pending); sender = gwthread_create(boxc_sender, newconn); if (sender == -1) { error(0, "Failed to start a new thread, disconnecting client <%s>", octstr_get_cstr(newconn->client_ip)); goto cleanup; } /* * We register newconn in the smsbox_list here but mark newconn as routable * after identification or first message received from smsbox. So we can avoid * a race condition for routable smsboxes (otherwise between startup and * registration we will forward some messages to smsbox). */ gw_rwlock_wrlock(smsbox_list_rwlock); gwlist_append(smsbox_list, newconn); gw_rwlock_unlock(smsbox_list_rwlock); gwlist_add_producer(newconn->outgoing); boxc_receiver(newconn); gwlist_remove_producer(newconn->outgoing); /* remove us from smsbox routing list */ gw_rwlock_wrlock(smsbox_list_rwlock); gwlist_delete_equal(smsbox_list, newconn); if (newconn->boxc_id) { dict_remove(smsbox_by_id, newconn->boxc_id); } gw_rwlock_unlock(smsbox_list_rwlock); /* * check if we in the shutdown phase and sms dequeueing thread * has removed the producer already */ if (gwlist_producer_count(newconn->incoming) > 0) gwlist_remove_producer(newconn->incoming); /* check if we are still waiting for ack's and semaphore locked */ if (dict_key_count(newconn->sent) >= smsbox_max_pending) semaphore_up(newconn->pending); /* allow sender to go down */ gwthread_join(sender); /* put not acked msgs into incoming queue */ keys = dict_keys(newconn->sent); while((key = gwlist_extract_first(keys)) != NULL) { msg = dict_remove(newconn->sent, key); gwlist_produce(incoming_sms, msg); octstr_destroy(key); } gw_assert(gwlist_len(keys) == 0); gwlist_destroy(keys, octstr_destroy_item); /* clear our send queue */ while((msg = gwlist_extract_first(newconn->incoming)) != NULL) { gwlist_produce(incoming_sms, msg); } cleanup: gw_assert(gwlist_len(newconn->incoming) == 0); gwlist_destroy(newconn->incoming, NULL); gw_assert(dict_key_count(newconn->sent) == 0); dict_destroy(newconn->sent); semaphore_destroy(newconn->pending); boxc_destroy(newconn); /* wakeup the dequeueing thread */ gwthread_wakeup(sms_dequeue_thread); gwlist_remove_producer(flow_threads); }
static void sms_to_smsboxes(void *arg) { Msg *newmsg, *startmsg, *msg; long i, len; int ret = -1; Boxc *boxc; gwlist_add_producer(flow_threads); newmsg = startmsg = msg = NULL; while(bb_status != BB_DEAD) { if (newmsg == startmsg) { /* check if we are in shutdown phase */ if (gwlist_producer_count(smsbox_list) == 0) break; if (ret == 0 || ret == -1) { /* debug("", 0, "time to sleep"); */ gwthread_sleep(60.0); /* debug("", 0, "wake up list len %ld", gwlist_len(incoming_sms)); */ /* shutdown ? */ if (gwlist_producer_count(smsbox_list) == 0 && gwlist_len(smsbox_list) == 0) break; } startmsg = msg = gwlist_consume(incoming_sms); /* debug("", 0, "gwlist_consume done 1"); */ newmsg = NULL; } else { newmsg = msg = gwlist_consume(incoming_sms); /* Back at the first message? */ if (newmsg == startmsg) { gwlist_insert(incoming_sms, 0, msg); continue; } } if (msg == NULL) break; gw_assert(msg_type(msg) == sms); /* debug("bb.sms", 0, "sms_boxc_router: handling message (%p vs %p)", msg, startmsg); */ ret = route_incoming_to_boxc(msg); if (ret == 1) startmsg = newmsg = NULL; else if (ret == -1) { gwlist_produce(incoming_sms, msg); } } gw_rwlock_rdlock(smsbox_list_rwlock); len = gwlist_len(smsbox_list); for (i=0; i < len; i++) { boxc = gwlist_get(smsbox_list, i); gwlist_remove_producer(boxc->incoming); } gw_rwlock_unlock(smsbox_list_rwlock); gwlist_remove_producer(flow_threads); }