/* * Main function for timer thread. */ static void watch_timers(void *arg) { Timerset *set; long top_time; long now; set = arg; while (!set->stopping) { lock(set); now = time(NULL); while (set->heap->len > 0 && set->heap->tab[0]->elapses <= now) { elapse_timer(set->heap->tab[0]); heap_delete(set->heap, 0); } /* * Now sleep until the next timer elapses. If there isn't one, * then just sleep very long. We will get woken up if the * top of the heap changes before we wake. */ if (set->heap->len == 0) { unlock(set); gwthread_sleep(1000000.0); } else { top_time = set->heap->tab[0]->elapses; unlock(set); gwthread_sleep(top_time - now); } } }
static void smsbox_thread(void *arg) { Connection *conn; Msg *msg; Octstr *os; Octstr *reply_msg; unsigned long count; msg = msg_create(sms); msg->sms.sender = octstr_create("123"); msg->sms.receiver = octstr_create("456"); msg->sms.msgdata = octstr_create("hello world"); reply_msg = msg_pack(msg); msg_destroy(msg); gwthread_sleep(1.0); conn = conn_open_tcp(bearerbox_host, port_for_smsbox, NULL); if (conn == NULL) { gwthread_sleep(2.0); conn = conn_open_tcp(bearerbox_host, port_for_smsbox, NULL); if (conn == NULL) panic(0, "Couldn't connect to bearerbox as smsbox"); } while (!quitting && conn_wait(conn, -1.0) != -1) { for (;;) { os = conn_read_withlen(conn); if (os == NULL) { if (conn_eof(conn) || conn_error(conn)) goto error; break; } msg = msg_unpack(os); if (msg == NULL || msg->type == wdp_datagram) error(0, "Bearerbox sent garbage to smsbox"); if (msg->type == sms) { if (first_from_bb == (time_t) -1) time(&first_from_bb); count = counter_increase(num_from_bearerbox) + 1; debug("test.smpp", 0, "Bearerbox sent sms #%ld <%s> to smsbox, sending reply.", count, octstr_get_cstr(msg->sms.msgdata)); if (count == max_to_esme) info(0, "Bearerbox has sent all messages to smsbox."); conn_write_withlen(conn, reply_msg); counter_increase(num_to_bearerbox); } msg_destroy(msg); octstr_destroy(os); time(&last_to_bb); } } error: conn_destroy(conn); octstr_destroy(reply_msg); debug("test.smpp", 0, "%s terminates.", __func__); }
DBPoolConn *dbpool_conn_consume(DBPool *p) { DBPoolConn *pc; gw_assert(p != NULL && p->pool != NULL); /* check for max connections and if 0 return NULL */ if (p->max_size < 1) return NULL; /* check if we have any connection */ while (p->curr_size < 1) { debug("dbpool", 0, "DBPool has no connections, reconnecting up to maximum..."); /* dbpool_increase ensure max_size is not exceeded so don't lock */ dbpool_increase(p, p->max_size - p->curr_size); if (p->curr_size < 1) gwthread_sleep(0.1); } /* garantee that you deliver a valid connection to the caller */ while ((pc = gwlist_consume(p->pool)) != NULL) { /* * XXX check that the connection is still existing. * Is this a performance bottle-neck?! */ if (!pc->conn || (p->db_ops->check && p->db_ops->check(pc->conn) != 0)) { /* something was wrong, reinitialize the connection */ /* lock dbpool for update */ gwlist_lock(p->pool); dbpool_conn_destroy(pc); p->curr_size--; /* unlock dbpool for update */ gwlist_unlock(p->pool); /* * maybe not needed, just try to get next connection, but it * can be dangeros if all connections where broken, then we will * block here for ever. */ while (p->curr_size < 1) { debug("dbpool", 0, "DBPool has too few connections, reconnecting up to maximum..."); /* dbpool_increase ensure max_size is not exceeded so don't lock */ dbpool_increase(p, p->max_size - p->curr_size); if (p->curr_size < 1) gwthread_sleep(0.1); } } else { break; } } return (pc->conn != NULL ? pc : NULL); }
static void main_thread() { while (httpbox_status == SMPP_RUNNING) { readQueueMessages(); gwthread_sleep(1.0); } }
/* * Send a message to the bearerbox for delivery to a phone. * Return >= 0 for success & count of splitted sms messages, * -1 for failure. Does not destroy the msg. */ static int send_message(Msg *msg) { unsigned long msg_count; List *list; gw_assert(msg != NULL); gw_assert(msg_type(msg) == sms); /* * Encode our smsbox-id to the msg structure. * This will allow bearerbox to return specific answers to the * same smsbox, mainly for DLRs and SMS proxy modes. */ if (smsbox_id != NULL) { msg->sms.boxc_id = octstr_duplicate(smsbox_id); } list = sms_split(msg, NULL, NULL, NULL, NULL, 1, 0, 100, MAX_SMS_OCTETS); msg_count = gwlist_len(list); gwlist_destroy(list, msg_destroy_item); debug("sms", 0, "message length %ld, sending %ld messages", octstr_len(msg->sms.msgdata), msg_count); if (delay > 0) gwthread_sleep(delay); /* pass message to bearerbox */ if (deliver_to_bearerbox(msg) != 0) return -1; return msg_count; }
void mbuni_mm1_queue_runner(volatile sig_atomic_t *rstop) { settings->qfs->mms_queue_run(octstr_get_cstr(settings->mm1_queuedir), sendNotify, settings->mm1_queue_interval, settings->maxthreads, rstop); gwthread_sleep(2); /* Wait for it to die. */ return; }
static void wait_for_connections(int fd, void (*function) (void *arg), List *waited) { int ret; int timeout = 10; /* 10 sec. */ gw_assert(function != NULL); while(sqlbox_status == SQL_RUNNING) { ret = gwthread_pollfd(fd, POLLIN, 1.0); if (sqlbox_status == SQL_SHUTDOWN) { if (ret == -1 || !timeout) break; else timeout--; } if (ret > 0) { gwthread_create(function, (void *)fd); gwthread_sleep(1.0); } else if (ret < 0) { if(errno==EINTR) continue; if(errno==EAGAIN) continue; error(errno, "wait_for_connections failed"); } } }
/* * check if the password matches. Return NULL if * it does (or is not required) */ static Octstr *httpd_check_authorization(List *cgivars, int status) { Octstr *password; static double sleep = 0.01; password = http_cgi_variable(cgivars, "password"); if (status) { if (ha_status_pw == NULL) return NULL; if (password == NULL) goto denied; if (octstr_compare(password, ha_password)!=0 && octstr_compare(password, ha_status_pw)!=0) goto denied; } else { if (password == NULL || octstr_compare(password, ha_password)!=0) goto denied; } sleep = 0.0; return NULL; /* allowed */ denied: gwthread_sleep(sleep); sleep += 1.0; /* little protection against brute force * password cracking */ return octstr_create("Denied"); }
int main(int argc, char **argv) { Connection *conn; Octstr *host = NULL; int port, i; gwlib_init(); get_and_set_debugs(argc, argv, NULL); host = octstr_create(argv[1]); port = atoi(argv[2]); i = 50; debug("",0,"Connecting to host '%s', port %d, looping %i times.", octstr_get_cstr(host), port, i); for (i = 0; i <= 50; i++) { conn = conn_open_tcp(host, port, NULL); if (conn == NULL) { panic(0, "Couldn't connect."); } debug("",0,"%d: connected.", i); gwthread_sleep(0.2); debug("",0,"%d: closing.", i); conn_destroy(conn); } octstr_destroy(host); gwlib_shutdown(); return 0; }
static void smsboxc_run(void *arg) { int fd; int port; gwlist_add_producer(flow_threads); gwthread_wakeup(MAIN_THREAD_ID); port = (int) *((long *)arg); fd = make_server_socket(port, NULL); /* XXX add interface_name if required */ if (fd < 0) { panic(0, "Could not open smsbox port %d", port); } /* * infinitely wait for new connections; * to shut down the system, SIGTERM is send and then * select drops with error, so we can check the status */ wait_for_connections(fd, run_smsbox, incoming_sms, smsbox_port_ssl); gwlist_remove_producer(smsbox_list); /* continue avalanche */ gwlist_remove_producer(outgoing_sms); /* all connections do the same, so that all must remove() before it * is completely over */ while(gwlist_wait_until_nonempty(smsbox_list) == 1) gwthread_sleep(1.0); /* close listen socket */ close(fd); gwthread_wakeup(sms_dequeue_thread); gwthread_join(sms_dequeue_thread); gwlist_destroy(smsbox_list, NULL); smsbox_list = NULL; gw_rwlock_destroy(smsbox_list_rwlock); smsbox_list_rwlock = NULL; /* destroy things related to smsbox routing */ dict_destroy(smsbox_by_id); smsbox_by_id = NULL; dict_destroy(smsbox_by_smsc); smsbox_by_smsc = NULL; dict_destroy(smsbox_by_receiver); smsbox_by_receiver = NULL; dict_destroy(smsbox_by_smsc_receiver); smsbox_by_smsc_receiver = NULL; gwlist_remove_producer(flow_threads); }
int main(int argc, char **argv) { int cf_index; Octstr *filename, *version; gwlib_init(); list_dict = dict_create(32, msg_list_destroy_item); cf_index = get_and_set_debugs(argc, argv, check_args); setup_signal_handlers(); if (argv[cf_index] == NULL) filename = octstr_create("httpClient.conf"); else filename = octstr_create(argv[cf_index]); cfg = cfg_create(filename); /* Adding cfg-checks to core */ cfg_add_hooks(smppbox_is_allowed_in_group, smppbox_is_single_group); if (cfg_read(cfg) == -1) panic(0, "Couldn't read configuration from `%s'.", octstr_get_cstr(filename)); octstr_destroy(filename); version = octstr_format("httpClient version %s gwlib", GW_VERSION); report_versions(octstr_get_cstr(version)); octstr_destroy(version); struct server_type *res = NULL; res = sqlbox_init_mysql(cfg); sqlbox_configure_mysql(cfg); init_smpp_server_box(cfg); http_client_box_run(); //gwthread_join_every(sql_to_smpp); //gwthread_join_every(smpp_to_sql); smpp_server_box_shutdown(); dict_destroy(list_dict); list_dict = NULL; cfg_destroy(cfg); if (restart_httpbox) { gwthread_sleep(1.0); } gw_smpp_leave(); gwlib_shutdown(); if (restart_httpbox) execvp(argv[0], argv); return 0; }
static Connection *cgw_open_send_connection(SMSCConn *conn) { PrivData *privdata = conn->data; int wait; Connection *server; Msg *msg; wait = 0; while (!privdata->shutdown) { /* Change status only if the first attempt to form a * connection fails, as it's possible that the SMSC closed the * connection because of idle timeout and a new one will be * created quickly. */ if (wait) { if (conn->status == SMSCCONN_ACTIVE) { mutex_lock(conn->flow_mutex); conn->status = SMSCCONN_RECONNECTING; mutex_unlock(conn->flow_mutex); } while ((msg = gwlist_extract_first(privdata->outgoing_queue))) bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_TEMPORARILY, NULL); info(0, "smsc_cgw: waiting for %d minutes before trying to connect again", wait); gwthread_sleep(wait * 60); wait = wait > 5 ? 10 : wait * 2; } else wait = 1; server = conn_open_tcp_with_port(privdata->host, privdata->port, privdata->our_port, conn->our_host); if (privdata->shutdown) { conn_destroy(server); return NULL; } if (server == NULL) { error(0, "smsc_cgw: opening TCP connection to %s failed", octstr_get_cstr(privdata->host)); continue; } if (conn->status != SMSCCONN_ACTIVE) { mutex_lock(conn->flow_mutex); conn->status = SMSCCONN_ACTIVE; conn->connect_time = time(NULL); mutex_unlock(conn->flow_mutex); bb_smscconn_connected(conn); } return server; } return NULL; }
static void client_thread(void *arg) { List *reqh; unsigned long i; long succeeded, failed; HTTPCaller *caller; char buf[1024]; long in_queue; Counter *counter = NULL; caller = arg; succeeded = 0; failed = 0; reqh = gwlist_create(); sprintf(buf, "%ld", (long) gwthread_self()); http_header_add(reqh, "X-Thread", buf); if (auth_username != NULL && auth_password != NULL) http_add_basic_auth(reqh, auth_username, auth_password); in_queue = 0; counter = counter_create(); for (;;) { i = counter_increase(counter); if (i >= max_requests) goto receive_rest; start_request(caller, reqh, i); if (interval > 0) gwthread_sleep(interval); ++in_queue; if (receive_reply(caller) == -1) ++failed; else ++succeeded; --in_queue; } receive_rest: while (in_queue > 0) { if (receive_reply(caller) == -1) ++failed; else ++succeeded; --in_queue; } counter_destroy(counter); http_destroy_headers(reqh); http_caller_destroy(caller); info(0, "This thread: %ld succeeded, %ld failed.", succeeded, failed); }
static void sql_list(Boxc *boxc) { Msg *msg; List *qlist, *save_list; qlist = gwlist_create(); gwlist_add_producer(qlist); save_list = gwlist_create(); gwlist_add_producer(save_list); while (sqlbox_status == SQL_RUNNING && boxc->alive) { if ( gw_sql_fetch_msg_list(qlist, limit_per_cycle) > 0 ) { while((gwlist_len(qlist)>0) && ((msg = gwlist_consume(qlist)) != NULL )) { if (charset_processing(msg) == -1) { error(0, "Could not charset process message, dropping it!"); msg_destroy(msg); continue; } if (global_sender != NULL && (msg->sms.sender == NULL || octstr_len(msg->sms.sender) == 0)) { msg->sms.sender = octstr_duplicate(global_sender); } /* convert validity and deferred to unix timestamp */ if (msg->sms.validity != SMS_PARAM_UNDEFINED) msg->sms.validity = time(NULL) + msg->sms.validity * 60; if (msg->sms.deferred != SMS_PARAM_UNDEFINED) msg->sms.deferred = time(NULL) + msg->sms.deferred * 60; send_msg(boxc->bearerbox_connection, boxc, msg); /* convert validity & deferred back to minutes */ if (save_mt && msg->sms.validity != SMS_PARAM_UNDEFINED) msg->sms.validity = (msg->sms.validity - time(NULL))/60; if (save_mt && msg->sms.deferred != SMS_PARAM_UNDEFINED) msg->sms.deferred = (msg->sms.deferred - time(NULL))/60; gwlist_produce(save_list, msg); } /* save_list also deletes and destroys messages */ gw_sql_save_list(save_list, octstr_imm("MT"), save_mt); } else { gwthread_sleep(SLEEP_BETWEEN_EMPTY_SELECTS); } } gwlist_remove_producer(qlist); gwlist_remove_producer(save_list); gwlist_destroy(qlist, msg_destroy_item); gwlist_destroy(save_list, msg_destroy_item); }
int restart_box(char **argv) { int rc; if (!(rc = fork())) { /* * Sleep a while in order to get father * process time to cleanup things */ gwthread_sleep(1.0); if (execvp(argv[0],argv) == -1) error(errno, "Unable to start new process."); } else if (rc == -1) error(errno, "Could not restart, exiting..."); return rc == -1 ? -1 : 0; }
static void push_thread(void *arg) { HTTPCaller *caller; long succeeded, failed, in_queue; unsigned long i; caller = arg; succeeded = 0; failed = 0; in_queue = 0; i = 0; for (;;) { while (in_queue < MAX_IN_QUEUE) { i = counter_increase(counter); if (i >= max_pushes) goto receive_rest; start_push(caller, i); if (wait_seconds > 0) gwthread_sleep(wait_seconds); ++in_queue; } while (in_queue >= MAX_IN_QUEUE) { if (receive_push_reply(caller) == -1) ++failed; else ++succeeded; --in_queue; } } receive_rest: while (in_queue > 0) { if (receive_push_reply(caller) == -1) ++failed; else ++succeeded; --in_queue; } http_caller_destroy(caller); info(0, "TEST_PPG: In thread %ld %ld succeeded, %ld failed", (long) gwthread_self(), succeeded, failed); }
int main(int argc, char **argv) { int cf_index; Octstr *filename; gwlib_init(); cf_index = get_and_set_debugs(argc, argv, check_args); setup_signal_handlers(); if (argv[cf_index] == NULL) { filename = octstr_create("sqlbox.conf"); } else { filename = octstr_create(argv[cf_index]); } cfg = cfg_create(filename); /* Adding cfg-checks to core */ cfg_add_hooks(sqlbox_is_allowed_in_group, sqlbox_is_single_group); if (cfg_read(cfg) == -1) panic(0, "Couldn't read configuration from `%s'.", octstr_get_cstr(filename)); octstr_destroy(filename); report_versions("sqlbox"); init_sqlbox(cfg); sqlboxc_run((void *)sqlbox_port); cfg_destroy(cfg); if (restart_sqlbox) { gwthread_sleep(1.0); } gw_sql_leave(); gwlib_shutdown(); if (restart_sqlbox) execvp(argv[0], argv); return 0; }
int main(void) { Dict *dict; Octstr *foo, *bar; unsigned long i; gwlib_init(); foo = octstr_imm("foo"); bar = octstr_imm("bar"); debug("",0,"Dict simple test."); dict = dict_create(10, NULL); dict_put(dict, foo, bar); info(0, "foo gives %s", octstr_get_cstr(dict_get(dict, foo))); if (dict_key_count(dict) == 1) info(0, "there is but one foo."); else error(0, "key count is %ld, should be 1.", dict_key_count(dict)); dict_destroy(dict); debug("",0,"Dict extended/huge test."); dict = dict_create(HUGE_SIZE, (void (*)(void *))octstr_destroy); for (i = 1; i <= HUGE_SIZE; i++) { unsigned long val; Octstr *okey, *oval; uuid_t id; char key[UUID_STR_LEN + 1]; uuid_generate(id); uuid_unparse(id, key); val = gw_rand(); okey = octstr_create(key); oval = octstr_format("%ld", val); dict_put(dict, okey, oval); } gwthread_sleep(5); /* give hash table some time */ if (dict_key_count(dict) == HUGE_SIZE) info(0, "ok, got %d entries in the dictionary.", HUGE_SIZE); else error(0, "key count is %ld, should be %d.", dict_key_count(dict), HUGE_SIZE); dict_destroy(dict); gwlib_shutdown(); return 0; }
static void send_smpp_thread(void *arg) { ESME *esme; Octstr *os; SMPP_PDU *pdu; unsigned long id; esme = arg; id = 0; while (!quitting && counter_value(num_to_esme) < max_to_esme) { id = counter_increase(num_to_esme) + 1; while (!quitting && counter_value(num_from_esme) + 500 < id) gwthread_sleep(1.0); if (quitting) break; pdu = smpp_pdu_create(deliver_sm, counter_increase(message_id_counter)); pdu->u.deliver_sm.source_addr = octstr_create("456"); pdu->u.deliver_sm.destination_addr = octstr_create("123"); pdu->u.deliver_sm.short_message = octstr_format("%ld", id); if (esme->version > 0x33) pdu->u.deliver_sm.receipted_message_id = octstr_create("receipted_message_id\0"); os = smpp_pdu_pack(NULL, pdu); conn_write(esme->conn, os); octstr_destroy(os); smpp_pdu_destroy(pdu); if (first_to_esme == (time_t) -1) time(&first_to_esme); debug("test.smpp", 0, "Delivered SMS %ld of %ld to bearerbox via SMPP.", id, max_to_esme); if ((id % enquire_interval) == 0) { pdu = smpp_pdu_create(enquire_link, counter_increase(message_id_counter)); os = smpp_pdu_pack(NULL, pdu); conn_write(esme->conn, os); octstr_destroy(os); smpp_pdu_destroy(pdu); debug("test.smpp", 0, "Sent enquire_link to bearerbox."); } } time(&last_to_esme); if (id == max_to_esme) info(0, "All messages sent to ESME."); debug("test.smpp", 0, "%s terminates.", __func__); }
/* * thread to write current store to file now and then, to prevent * it from becoming far too big (slows startup) */ static void store_dumper(void *arg) { time_t now; int busy = 0; while (active) { now = time(NULL); /* * write store to file up to each N. second, providing * that something happened or if we are constantly busy. */ if (now - last_dict_mod > dump_frequency || busy) { store_dump(); /* * make sure that no new dump is done for a while unless * something happens. This moves the trigger in the future * and allows the if statement to pass if nothing happened * in the mean time while sleeping. The busy flag is needed * to garantee we do dump in case we are constantly busy * and hence the difference between now and last dict * operation is less then dump frequency, otherwise we * would never dump. This is for constant high load. */ last_dict_mod = time(NULL) + 3600*24; busy = 0; } else { busy = (now - last_dict_mod) > 0; } gwthread_sleep(dump_frequency); } store_dump(); if (file != NULL) fclose(file); octstr_destroy(filename); octstr_destroy(newfile); octstr_destroy(bakfile); mutex_destroy(file_mutex); dict_destroy(sms_dict); /* set all vars to NULL */ filename = newfile = bakfile = NULL; file_mutex = NULL; sms_dict = NULL; }
static void wrapper_receiver(void *arg) { Msg *msg; SMSCConn *conn = arg; SmscWrapper *wrap = conn->data; /* SmscWrapper *wrap = conn->data; ** non-used */ double sleep = 0.0001; /* Make sure we log into our own log-file if defined */ log_thread_to(conn->log_idx); /* remove messages from SMSC until we are killed */ while(conn->why_killed == SMSCCONN_ALIVE) { gwlist_consume(wrap->stopped); /* block here if suspended/isolated */ msg = sms_receive(conn); if (msg) { debug("bb.sms", 0, "smscconn (%s): new message received", octstr_get_cstr(conn->name)); sleep = 0.0001; bb_smscconn_receive(conn, msg); } else { /* note that this implementations means that we sleep even * when we fail connection.. but time is very short, anyway */ gwthread_sleep(sleep); /* gradually sleep longer and longer times until something starts to * happen - this of course reduces response time, but that's better than * extensive CPU usage when it is not used */ sleep *= 2; if (sleep >= 2.0) sleep = 1.999999; } } conn->why_killed = SMSCCONN_KILLED_SHUTDOWN; /* this thread is joined at sender */ }
static void wait_for_connections(int fd, void (*function) (void *arg), List *waited, int ssl) { int ret; int timeout = 10; /* 10 sec. */ gw_assert(function != NULL); while(bb_status != BB_DEAD) { /* if we are being shutdowned, as long as there is * messages in incoming list allow new connections, but when * list is empty, exit. * Note: We have timeout (defined above) for which we allow new connections. * Otherwise we wait here for ever! */ if (bb_status == BB_SHUTDOWN) { ret = gwlist_wait_until_nonempty(waited); if (ret == -1 || !timeout) break; else timeout--; } /* block here if suspended */ gwlist_consume(suspended); ret = gwthread_pollfd(fd, POLLIN, 1.0); if (ret > 0) { Boxc *newconn = accept_boxc(fd, ssl); if (newconn != NULL) { gwthread_create(function, newconn); gwthread_sleep(1.0); } else { error(0, "Failed to create new boxc connection."); } } else if (ret < 0 && errno != EINTR && errno != EAGAIN) error(errno, "bb_boxc::wait_for_connections failed"); } }
static void wapboxc_run(void *arg) { int fd, port; gwlist_add_producer(flow_threads); gwthread_wakeup(MAIN_THREAD_ID); port = (int) *((long*)arg); fd = make_server_socket(port, NULL); /* XXX add interface_name if required */ if (fd < 0) { panic(0, "Could not open wapbox port %d", port); } wait_for_connections(fd, run_wapbox, incoming_wdp, wapbox_port_ssl); /* continue avalanche */ gwlist_remove_producer(outgoing_wdp); /* wait for all connections to die and then remove list */ while(gwlist_wait_until_nonempty(wapbox_list) == 1) gwthread_sleep(1.0); /* wait for wdp_to_wapboxes to exit */ while(gwlist_consume(wapbox_list)!=NULL) ; /* close listen socket */ close(fd); gwlist_destroy(wapbox_list, NULL); wapbox_list = NULL; gwlist_remove_producer(flow_threads); }
/* * Send a message to the bearerbox for delivery to a phone. * Return >= 0 for success & count of splitted sms messages, * -1 for failure. Does not destroy the msg. */ static int send_message(Msg *msg) { unsigned long msg_count; List *list; gw_assert(msg != NULL); gw_assert(msg_type(msg) == sms); /* * Encode our smsbox-id to the msg structure. * This will allow bearerbox to return specific answers to the * same smsbox, mainly for DLRs and SMS proxy modes. * * In addition the -x flag can be used to identify the mtbatch * instance with an own smsbox-id, but let the normal smsbox * daemons handle the DLRs coming back, as the mtbatch shuts down * after all MTs have been injected. It's not meant to process * the DLR messages. */ if (no_smsbox_id == 0 && smsbox_id != NULL) { msg->sms.boxc_id = octstr_duplicate(smsbox_id); } list = sms_split(msg, NULL, NULL, NULL, NULL, 1, 0, 100, MAX_SMS_OCTETS); msg_count = gwlist_len(list); gwlist_destroy(list, msg_destroy_item); debug("sms", 0, "message length %ld, sending %ld messages", octstr_len(msg->sms.msgdata), msg_count); if (delay > 0) gwthread_sleep(delay); /* pass message to bearerbox */ if (deliver_to_bearerbox(msg) != 0) return -1; return msg_count; }
static void sql_single(Boxc *boxc) { Msg *msg; while (sqlbox_status == SQL_RUNNING && boxc->alive) { if ((msg = gw_sql_fetch_msg()) != NULL) { if (charset_processing(msg) == -1) { error(0, "Could not charset process message, dropping it!"); msg_destroy(msg); continue; } if (global_sender != NULL && (msg->sms.sender == NULL || octstr_len(msg->sms.sender) == 0)) { msg->sms.sender = octstr_duplicate(global_sender); } /* convert validity and deferred to unix timestamp */ if (msg->sms.validity != SMS_PARAM_UNDEFINED) msg->sms.validity = time(NULL) + msg->sms.validity * 60; if (msg->sms.deferred != SMS_PARAM_UNDEFINED) msg->sms.deferred = time(NULL) + msg->sms.deferred * 60; send_msg(boxc->bearerbox_connection, boxc, msg); if (save_mt) { /* convert validity & deferred back to minutes * TODO clarify why we fetched message from DB and then insert it back here??? */ if (msg->sms.validity != SMS_PARAM_UNDEFINED) msg->sms.validity = (msg->sms.validity - time(NULL))/60; if (msg->sms.deferred != SMS_PARAM_UNDEFINED) msg->sms.deferred = (msg->sms.deferred - time(NULL))/60; gw_sql_save_msg(msg, octstr_imm("MT")); } } else { gwthread_sleep(SLEEP_BETWEEN_EMPTY_SELECTS); } msg_destroy(msg); } }
int main(int argc, char **argv) { int opt; unsigned long sended = 0; Octstr *cf, *rf; gwlib_init(); bb_host = octstr_create("localhost"); bb_port = 13001; bb_ssl = 0; while ((opt = getopt(argc, argv, "hv:b:p:si:n:a:f:D:u:d:r:")) != EOF) { switch (opt) { case 'v': log_set_output_level(atoi(optarg)); break; case 'b': octstr_destroy(bb_host); bb_host = octstr_create(optarg); break; case 'p': bb_port = atoi(optarg); break; case 's': bb_ssl = 1; break; case 'i': smsbox_id = octstr_create(optarg); break; case 'n': service = octstr_create(optarg); break; case 'a': account = octstr_create(optarg); break; case 'f': from = octstr_create(optarg); break; case 'D': dlr_mask = atoi(optarg); break; case 'u': dlr_url = octstr_create(optarg); break; case 'd': delay = atof(optarg); break; case 'r': smsc_id = octstr_create(optarg); break; case '?': default: error(0, "Invalid option %c", opt); help(); panic(0, "Stopping."); } } if (optind == argc || argc-optind < 2) { help(); exit(1); } /* check some mandatory elements */ if (from == NULL) panic(0,"Sender address not specified. Use option -f to specify sender address."); if ((DLR_IS_ENABLED(dlr_mask) && dlr_url == NULL) || (!DLR_IS_ENABLED(dlr_mask) && dlr_url != NULL)) panic(0,"dlr-url address OR dlr-mask not specified. Use option -D or -u to specify dlr values"); rf = octstr_create(argv[argc-1]); cf = octstr_create(argv[argc-2]); report_versions("mtbatch"); write_pid_file(); init_batch(cf, rf); connect_to_bearerbox(bb_host, bb_port, bb_ssl, NULL /* bb_our_host */); identify_to_bearerbox(); gwthread_create(read_messages_from_bearerbox, NULL); sended = run_batch(); /* avoid exiting before sending all msgs */ while(sended > counter_value(counter)) { gwthread_sleep(0.1); } program_status = shutting_down; gwthread_join_all(); octstr_destroy(bb_host); octstr_destroy(smsbox_id); octstr_destroy(content); octstr_destroy(service); octstr_destroy(account); octstr_destroy(dlr_url); octstr_destroy(smsc_id); counter_destroy(counter); gwlist_destroy(lines, octstr_destroy_item); gwlib_shutdown(); return 0; }
static int reconnect(SMSCConn *conn) { SmscWrapper *wrap = conn->data; Msg *msg; int ret; int wait = 1; /* disable double-reconnect * NOTE: it is still possible that we do double-connect if * first thread gets through this if-statement and then * execution switches to another thread.. this can be avoided * via double-mutex system, but I do not feel it is worth it, * maybe later --rpr */ if (conn->status == SMSCCONN_RECONNECTING) { mutex_lock(wrap->reconnect_mutex); /* wait here */ mutex_unlock(wrap->reconnect_mutex); return 0; } mutex_lock(wrap->reconnect_mutex); debug("bb.sms", 0, "smsc_wrapper <%s>: reconnect started", octstr_get_cstr(conn->name)); while((msg = gwlist_extract_first(wrap->outgoing_queue))!=NULL) { bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_TEMPORARILY, NULL); } conn->status = SMSCCONN_RECONNECTING; while(conn->why_killed == SMSCCONN_ALIVE) { ret = smsc_reopen(wrap->smsc); if (ret == 0) { info(0, "Re-open of %s succeeded.", octstr_get_cstr(conn->name)); mutex_lock(conn->flow_mutex); conn->status = SMSCCONN_ACTIVE; conn->connect_time = time(NULL); mutex_unlock(conn->flow_mutex); bb_smscconn_connected(conn); break; } else if (ret == -2) { error(0, "Re-open of %s failed permanently", octstr_get_cstr(conn->name)); mutex_lock(conn->flow_mutex); conn->status = SMSCCONN_DISCONNECTED; mutex_unlock(wrap->reconnect_mutex); mutex_unlock(conn->flow_mutex); return -1; /* permanent failure */ } else { error(0, "Re-open to <%s> failed, retrying after %d minutes...", octstr_get_cstr(conn->name), wait); gwthread_sleep(wait*60.0); wait = wait > 10 ? 10 : wait * 2 + 1; } } mutex_unlock(wrap->reconnect_mutex); return 0; }
/* * Thread to handle finished sendings */ static void httpsmsc_send_cb(void *arg) { SMSCConn *conn = arg; ConnData *conndata = conn->data; Msg *msg; int status; List *headers; Octstr *final_url, *body; /* Make sure we log into our own log-file if defined */ log_thread_to(conn->log_idx); while(conndata->shutdown == 0 || counter_value(conndata->open_sends)) { msg = http_receive_result(conndata->http_ref, &status, &final_url, &headers, &body); if (msg == NULL) break; /* they told us to die, by unlocking */ counter_decrease(conndata->open_sends); if (conndata->max_pending_sends) semaphore_up(conndata->max_pending_sends); /* Handle various states here. */ /* request failed and we are not in shutdown mode */ if (status == -1 && conndata->shutdown == 0) { error(0, "HTTP[%s]: Couldn't connect to SMS center." "(retrying in %ld seconds) %ld.", octstr_get_cstr(conn->id), conn->reconnect_delay, counter_value(conndata->open_sends)); mutex_lock(conn->flow_mutex); conn->status = SMSCCONN_RECONNECTING; mutex_unlock(conn->flow_mutex); /* XXX how should we know whether it's temp. error ?? */ bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_TEMPORARILY, NULL); /* * Just sleep reconnect delay and set conn to ACTIVE again; * otherwise if no pending request are here, we leave conn in * RECONNECTING state for ever and no routing (trials) take place. */ if (counter_value(conndata->open_sends) == 0) { gwthread_sleep(conn->reconnect_delay); /* and now enable routing again */ mutex_lock(conn->flow_mutex); conn->status = SMSCCONN_ACTIVE; time(&conn->connect_time); mutex_unlock(conn->flow_mutex); /* tell bearerbox core that we are connected again */ bb_smscconn_connected(conn); } continue; } /* request failed and we *are* in shutdown mode, drop the message */ else if (status == -1 && conndata->shutdown == 1) { bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_SHUTDOWN, NULL); } /* request succeeded */ else { /* we received a response, so this link is considered online again */ if (conn->status != SMSCCONN_ACTIVE) { mutex_lock(conn->flow_mutex); conn->status = SMSCCONN_ACTIVE; time(&conn->connect_time); mutex_unlock(conn->flow_mutex); /* tell bearerbox core that we are connected again */ bb_smscconn_connected(conn); } conndata->callbacks->parse_reply(conn, msg, status, headers, body); } http_destroy_headers(headers); octstr_destroy(final_url); octstr_destroy(body); } debug("smsc.http", 0, "HTTP[%s]: httpsmsc_send_cb dying", octstr_get_cstr(conn->id)); conndata->shutdown = 1; if (counter_value(conndata->open_sends)) { warning(0, "HTTP[%s]: Shutdown while <%ld> requests are pending.", octstr_get_cstr(conn->id), counter_value(conndata->open_sends)); } }
/* * Thread to send queued messages */ static void httpsmsc_sender(void *arg) { SMSCConn *conn = arg; ConnData *conndata = conn->data; Msg *msg; double delay = 0; /* Make sure we log into our own log-file if defined */ log_thread_to(conn->log_idx); if (conn->throughput) { delay = 1.0 / conn->throughput; } while (conndata->shutdown == 0) { /* check if we can send ; otherwise block on semaphore */ if (conndata->max_pending_sends) semaphore_down(conndata->max_pending_sends); if (conndata->shutdown) { if (conndata->max_pending_sends) semaphore_up(conndata->max_pending_sends); break; } msg = gwlist_consume(conndata->msg_to_send); if (msg == NULL) break; /* obey throughput speed limit, if any */ if (conn->throughput > 0) { gwthread_sleep(delay); } counter_increase(conndata->open_sends); if (conndata->callbacks->send_sms(conn, msg) == -1) { counter_decrease(conndata->open_sends); if (conndata->max_pending_sends) semaphore_up(conndata->max_pending_sends); } } /* put outstanding sends back into global queue */ while((msg = gwlist_extract_first(conndata->msg_to_send))) bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_SHUTDOWN, NULL); /* if there no receiver shutdown */ if (conndata->port <= 0) { /* unblock http_receive_result() if there are no open sends */ if (counter_value(conndata->open_sends) == 0) http_caller_signal_shutdown(conndata->http_ref); if (conndata->send_cb_thread != -1) { gwthread_wakeup(conndata->send_cb_thread); gwthread_join(conndata->send_cb_thread); } mutex_lock(conn->flow_mutex); conn->status = SMSCCONN_DEAD; mutex_unlock(conn->flow_mutex); if (conndata->callbacks != NULL && conndata->callbacks->destroy != NULL) conndata->callbacks->destroy(conn); conn->data = NULL; conndata_destroy(conndata); bb_smscconn_killed(); } }
static void parachute_start(const char *myname, const char *panic_script) { time_t last_start = 0, last_panic = 0; long respawn_count = 0; int status; if (panic_script && !is_executable(panic_script)) panic(0, "Panic script `%s' is not executable for us.", panic_script); /* setup sighandler */ parachute_init_signals(0); for (;;) { if (respawn_count > 0 && difftime(time(NULL), last_start) < 10) { error(0, "Child process died too fast, disabling for 30 sec."); gwthread_sleep(30.0); } if (!(child_pid = fork())) { /* child process */ parachute_init_signals(1); /* reset sighandlers */ return; } else if (child_pid < 0) { error(errno, "Could not start child process! Will retry in 5 sec."); gwthread_sleep(5.0); continue; } else { /* father process */ time(&last_start); info(0, "Child process with PID (%ld) started.", (long) child_pid); do { if (waitpid(child_pid, &status, 0) == child_pid) { /* check here why child terminated */ if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { info(0, "Child process exited gracefully, exit..."); gwlib_shutdown(); exit(0); } else if (WIFEXITED(status)) { error(0, "Caught child PID (%ld) which died with return code %d", (long) child_pid, WEXITSTATUS(status)); child_pid = -1; } else if (WIFSIGNALED(status)) { error(0, "Caught child PID (%ld) which died due to signal %d", (long) child_pid, WTERMSIG(status)); child_pid = -1; } } else if (errno != EINTR) { error(errno, "Error while waiting of child process."); } } while(child_pid > 0); if (parachute_shutdown) { /* may only happens if child process crashed while shutdown */ info(0, "Child process crashed while shutdown. Exiting due to signal..."); info(0, "Going into gwlib_shutdown..."); gwlib_shutdown(); info(0, "gwlib_shutdown done... Bye bye..."); exit(WIFEXITED(status) ? WEXITSTATUS(status) : 0); } /* check whether it's panic while start */ if (respawn_count == 0 && difftime(time(NULL), last_start) < 2) { info(0, "Child process crashed while starting. Exiting..."); info(0, "Going into gwlib_shutdown..."); gwlib_shutdown(); info(0, "gwlib_shutdown done... Bye bye..."); exit(WIFEXITED(status) ? WEXITSTATUS(status) : 1); } respawn_count++; if (panic_script && myname && difftime(time(NULL), last_panic) > 300) { time(&last_panic); debug("kannel", 0, "Executing panic script: %s %s %ld", panic_script, myname, respawn_count); execute_panic_script(panic_script, "%s %ld", myname, respawn_count); } /* sleep a while to get e.g. sockets released */ gwthread_sleep(5.0); } } }