/* * this function receives an WDP message and checks if a UDP * service for this client has to be created */ static int udp_addwdp_from_client(Msg *msg) { Udpc *udpc; Octstr *map_addr; Octstr *os; Octstr *source; if (!udp_running) return -1; assert(msg != NULL); assert(msg_type(msg) == wdp_datagram); /* * Check if there is allready a bound UDP port for this mapping. * If not create a mapping and bind the mapped UDP port * The mapped port is simply 2x of the client port. */ if ((udpc = udpc_find_mapping(msg, 1)) == NULL) { info(0, "Creating UDP mapping <%s:%ld> <-> <%s:%ld>", octstr_get_cstr(msg->wdp_datagram.source_address), msg->wdp_datagram.source_port, octstr_get_cstr(msg->wdp_datagram.destination_address), msg->wdp_datagram.source_port*2); map_addr = udp_create_address(msg->wdp_datagram.source_address, msg->wdp_datagram.source_port); add_service(msg->wdp_datagram.source_port * 2, octstr_get_cstr(interface_name), map_addr); /* now we should find it in the udpc_list */ if ((udpc = udpc_find_mapping(msg, 1)) == NULL) panic(0,"Could not find UDP mapping, internal error"); } /* now swap the message addressing */ octstr_destroy(msg->wdp_datagram.source_address); octstr_destroy(msg->wdp_datagram.destination_address); os = octstr_duplicate(interface_name); source = udp_create_address(os, msg->wdp_datagram.source_port * 2); msg->wdp_datagram.source_address = udp_get_ip(source); msg->wdp_datagram.source_port = udp_get_port(source); msg->wdp_datagram.destination_address = octstr_duplicate(wapgw); msg->wdp_datagram.destination_port = CONNECTION_ORIENTED_PORT; octstr_destroy(os); gwlist_produce(udpc->outgoing_list, msg); return -1; }
/* * This timer has elapsed. Do the housekeeping. We have its set locked. */ static void elapse_timer(Timer *timer) { gw_assert(timer != NULL); gw_assert(timer->timerset != NULL); /* This must be true because abort_elapsed is always called * before a timer is activated. */ gw_assert(timer->elapsed_data == NULL); timer->elapsed_data = timer->data; timer->elapses = -1; if (timer->output != NULL) gwlist_produce(timer->output, timer->elapsed_data); if (timer->callback != NULL) timer->callback(timer->elapsed_data); }
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); }
/* * this function receives an WDP message and adds it to * corresponding outgoing_list. */ static int udp_addwdp_from_server(Msg *msg) { Udpc *udpc; Octstr *os; Octstr *source; if (!udp_running) return -1; assert(msg != NULL); assert(msg_type(msg) == wdp_datagram); octstr_destroy(msg->wdp_datagram.source_address); msg->wdp_datagram.source_address = octstr_create(octstr_get_cstr(msg->wdp_datagram.destination_address)); msg->wdp_datagram.source_port = msg->wdp_datagram.destination_port; if ((udpc = udpc_find_mapping(msg, 0)) == NULL) /* there should have been one */ panic(0,"Could not find UDP mapping, internal error"); /* insert the found mapped destination */ octstr_destroy(msg->wdp_datagram.source_address); octstr_destroy(msg->wdp_datagram.destination_address); msg->wdp_datagram.destination_address = udp_get_ip(udpc->map_addr); msg->wdp_datagram.destination_port = udp_get_port(udpc->map_addr); /* now search for our inbound UDP socket */ os = octstr_duplicate(interface_name); source = udp_create_address(os, server_port); msg->wdp_datagram.source_address = udp_get_ip(source); msg->wdp_datagram.source_port = udp_get_port(source); if ((udpc = udpc_find_mapping(msg, 0)) == NULL) panic(0,"Could not find main inbound UDP socket, internal error"); /* * ok, got the destination, got the socket, * now put it on the outbound queue */ gwlist_produce(udpc->outgoing_list, msg); octstr_destroy(os); return 0; }
void cgw_check_acks(PrivData *privdata) { time_t current_time; int i; current_time = time(NULL); if (privdata->unacked && (current_time > privdata->check_time + 30)) { privdata->check_time = current_time; for (i = 0; i < CGW_TRN_MAX; i++) if (privdata->sendtime[i] && privdata->sendtime[i] < (current_time - privdata->waitack)) { privdata->sendtime[i] = 0; privdata->unacked--; warning(0, "smsc_cgw: received neither OK nor ERR for message %d " "in %d seconds, resending message", i, privdata->waitack); gwlist_produce(privdata->outgoing_queue, privdata->sendmsg[i]); } } }
static int cgw_send_loop(SMSCConn *conn, Connection *server) { PrivData *privdata = conn->data; struct cgwop *cgwop; Msg *msg; int firsttrn; /* Send messages in queue */ while ((msg = gwlist_extract_first(privdata->outgoing_queue)) != NULL) { firsttrn = privdata->nexttrn; while (privdata->sendtime[privdata->nexttrn] != 0) { if (++privdata->nexttrn >= CGW_TRN_MAX) privdata->nexttrn = 0; if (privdata->nexttrn == firsttrn) { /* no available trn */ /* this happens too many messages are sent, and old messages * haven't been acked. In this case, increase size of * CGW_TRN_MAX */ info(0, "cgw: Saturated, increase size of CGW_TRN_MAX!"); gwlist_produce(privdata->outgoing_queue, msg); return 1; /* re-insert, and go check for acks */ } } cgwop = msg_to_cgwop(privdata, msg, privdata->nexttrn); if (cgwop == NULL) { info(0, "cgw: cgwop == NULL"); return 0; } privdata->sendmsg[privdata->nexttrn] = msg; privdata->sendtime[privdata->nexttrn] = time(NULL); if (cgwop_send(server, cgwop) == -1) { cgwop_destroy(cgwop); info(0, "cgw: Unable to send (cgwop_send() == -1)"); return -1; } privdata->unacked++; cgwop_destroy(cgwop); } return 0; }
Semaphore *semaphore_create(long n) { Semaphore *semaphore; #ifndef HAVE_SEMAPHORE static char item; #endif semaphore = gw_malloc(sizeof(*semaphore)); #ifdef HAVE_SEMAPHORE if (sem_init(&semaphore->sem, 0, (unsigned int) n) != 0) panic(errno, "Could not initialize semaphore."); #else semaphore->list = gwlist_create(); gwlist_add_producer(semaphore->list); while (n-- > 0) gwlist_produce(semaphore->list, &item); #endif return semaphore; }
static int httpsmsc_send(SMSCConn *conn, Msg *msg) { ConnData *conndata = conn->data; Msg *sms; /* don't crash if no send_sms handle defined */ if (!conndata || !conndata->callbacks->send_sms) return -1; sms = msg_duplicate(msg); /* convert character encoding if required */ if (msg->sms.coding == DC_7BIT && conndata->alt_charset && charset_convert(sms->sms.msgdata, DEFAULT_CHARSET, octstr_get_cstr(conndata->alt_charset)) != 0) { error(0, "Failed to convert msgdata from charset <%s> to <%s>, will send as is.", DEFAULT_CHARSET, octstr_get_cstr(conndata->alt_charset)); } gwlist_produce(conndata->msg_to_send, sms); return 0; }
static void boxc_receiver(void *arg) { Boxc *conn = arg; Msg *msg, *mack; /* remove messages from socket until it is closed */ while (bb_status != BB_DEAD && conn->alive) { gwlist_consume(suspended); /* block here if suspended */ msg = read_from_box(conn); if (msg == NULL) { /* garbage/connection lost */ conn->alive = 0; break; } /* we don't accept new messages in shutdown phase */ if ((bb_status == BB_SHUTDOWN || bb_status == BB_DEAD) && msg_type(msg) == sms) { mack = msg_create(ack); uuid_copy(mack->ack.id, msg->sms.id); mack->ack.time = msg->sms.time; mack->ack.nack = ack_failed_tmp; msg_destroy(msg); send_msg(conn, mack); msg_destroy(mack); continue; } if (msg_type(msg) == sms && conn->is_wap == 0) { debug("bb.boxc", 0, "boxc_receiver: sms received"); /* deliver message to queue */ deliver_sms_to_queue(msg, conn); if (conn->routable == 0) { conn->routable = 1; /* wakeup the dequeue thread */ gwthread_wakeup(sms_dequeue_thread); } } else if (msg_type(msg) == wdp_datagram && conn->is_wap) { debug("bb.boxc", 0, "boxc_receiver: got wdp from wapbox"); /* XXX we should block these in SHUTDOWN phase too, but we need ack/nack msgs implemented first. */ gwlist_produce(conn->outgoing, msg); } else if (msg_type(msg) == sms && conn->is_wap) { debug("bb.boxc", 0, "boxc_receiver: got sms from wapbox"); /* should be a WAP push message, so tried it the same way */ deliver_sms_to_queue(msg, conn); if (conn->routable == 0) { conn->routable = 1; /* wakeup the dequeue thread */ gwthread_wakeup(sms_dequeue_thread); } } else { if (msg_type(msg) == heartbeat) { if (msg->heartbeat.load != conn->load) debug("bb.boxc", 0, "boxc_receiver: heartbeat with " "load value %ld received", msg->heartbeat.load); conn->load = msg->heartbeat.load; } else if (msg_type(msg) == ack) { if (msg->ack.nack == ack_failed_tmp) { Msg *orig; boxc_sent_pop(conn, msg, &orig); if (orig != NULL) /* retry this message */ gwlist_append(conn->retry, orig); } else { boxc_sent_pop(conn, msg, NULL); store_save(msg); } debug("bb.boxc", 0, "boxc_receiver: got ack"); } /* if this is an identification message from an smsbox instance */ else if (msg_type(msg) == admin && msg->admin.command == cmd_identify) { /* * any smsbox sends this command even if boxc_id is NULL, * but we will only consider real identified boxes */ if (msg->admin.boxc_id != NULL) { /* and add the boxc_id into conn for boxc_status() output */ if (conn->boxc_id != NULL) { dict_remove(smsbox_by_id, msg->admin.boxc_id); octstr_destroy(conn->boxc_id); } conn->boxc_id = msg->admin.boxc_id; msg->admin.boxc_id = NULL; /* add this identified smsbox to the dictionary */ /* XXX check for equal boxc_id in Dict, otherwise we overwrite it */ dict_put(smsbox_by_id, conn->boxc_id, conn); debug("bb.boxc", 0, "boxc_receiver: got boxc_id <%s> from <%s>", octstr_get_cstr(conn->boxc_id), octstr_get_cstr(conn->client_ip)); } conn->routable = 1; /* wakeup the dequeue thread */ gwthread_wakeup(sms_dequeue_thread); } else warning(0, "boxc_receiver: unknown msg received from <%s>, " "ignored", octstr_get_cstr(conn->client_ip)); msg_destroy(msg); } } }
/* * Route the incoming message to one of the following input queues: * a specific smsbox conn * a random smsbox conn if no shortcut routing and msg->sms.boxc_id match * * BEWARE: All logic inside here should be fast, hence speed processing * optimized, because every single MO message passes this function and we * have to ensure that no unncessary overhead is done. */ int route_incoming_to_boxc(Msg *msg) { Boxc *bc = NULL, *best = NULL; Octstr *s, *r, *rs; long len, b, i; int full_found = 0; s = r = NULL; gw_assert(msg_type(msg) == sms); /* msg_dump(msg, 0); */ /* * We have a specific route to pass this msg to smsbox-id * Lookup the connection in the dictionary. */ gw_rwlock_rdlock(smsbox_list_rwlock); if (gwlist_len(smsbox_list) == 0) { gw_rwlock_unlock(smsbox_list_rwlock); warning(0, "smsbox_list empty!"); if (max_incoming_sms_qlength < 0 || max_incoming_sms_qlength > gwlist_len(incoming_sms)) { gwlist_produce(incoming_sms, msg); return 0; } else return -1; } if (octstr_len(msg->sms.boxc_id) > 0) { bc = dict_get(smsbox_by_id, msg->sms.boxc_id); if (bc == NULL) { /* * something is wrong, this was the smsbox connection we used * for sending, so it seems this smsbox is gone */ warning(0,"Could not route message to smsbox id <%s>, smsbox is gone!", octstr_get_cstr(msg->sms.boxc_id)); } } else { /* * Check if we have a "smsbox-route" for this msg. * Where the shortcode route has a higher priority then the smsc-id rule. * Highest priority has the combined <shortcode>:<smsc-id> route. */ Octstr *os = octstr_format("%s:%s", octstr_get_cstr(msg->sms.receiver), octstr_get_cstr(msg->sms.smsc_id)); s = (msg->sms.smsc_id ? dict_get(smsbox_by_smsc, msg->sms.smsc_id) : NULL); r = (msg->sms.receiver ? dict_get(smsbox_by_receiver, msg->sms.receiver) : NULL); rs = (os ? dict_get(smsbox_by_smsc_receiver, os) : NULL); octstr_destroy(os); bc = rs ? dict_get(smsbox_by_id, rs) : (r ? dict_get(smsbox_by_id, r) : (s ? dict_get(smsbox_by_id, s) : NULL)); } /* check if we found our routing */ if (bc != NULL) { if (max_incoming_sms_qlength < 0 || max_incoming_sms_qlength > gwlist_len(bc->incoming)) { gwlist_produce(bc->incoming, msg); gw_rwlock_unlock(smsbox_list_rwlock); return 1; /* we are done */ } else { gw_rwlock_unlock(smsbox_list_rwlock); return -1; } } else if (s != NULL || r != NULL || octstr_len(msg->sms.boxc_id) > 0) { gw_rwlock_unlock(smsbox_list_rwlock); /* * we have routing defined, but no smsbox connected at the moment. * put msg into global incoming queue and wait until smsbox with * such boxc_id connected. */ if (max_incoming_sms_qlength < 0 || max_incoming_sms_qlength > gwlist_len(incoming_sms)) { gwlist_produce(incoming_sms, msg); return 0; } else return -1; } /* * ok, none of the routing things applied previously, so route it to * a random smsbox. */ /* take random smsbox from list, and then check all smsboxes * and select the one with lowest load level - if tied, the first * one */ len = gwlist_len(smsbox_list); b = gw_rand() % len; for(i = 0; i < gwlist_len(smsbox_list); i++) { bc = gwlist_get(smsbox_list, (i+b) % len); if (bc->boxc_id != NULL || bc->routable == 0) bc = NULL; if (bc != NULL && max_incoming_sms_qlength > 0 && gwlist_len(bc->incoming) > max_incoming_sms_qlength) { full_found = 1; bc = NULL; } if ((bc != NULL && best != NULL && bc->load < best->load) || (bc != NULL && best == NULL)) { best = bc; } } if (best != NULL) { best->load++; gwlist_produce(best->incoming, msg); } gw_rwlock_unlock(smsbox_list_rwlock); if (best == NULL && full_found == 0) { warning(0, "smsbox_list empty!"); if (max_incoming_sms_qlength < 0 || max_incoming_sms_qlength > gwlist_len(incoming_sms)) { gwlist_produce(incoming_sms, msg); return 0; } else return -1; } else if (best == NULL && full_found == 1) return -1; return 1; }
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); }
void dbpool_conn_produce(DBPoolConn *pc) { gw_assert(pc != NULL && pc->conn != NULL && pc->pool != NULL && pc->pool->pool != NULL); gwlist_produce(pc->pool->pool, pc); }
int smpp_pdu_init(Cfg *cfg) { CfgGroup *grp; List *l; if (initialized) return 0; l = cfg_get_multi_group(cfg, octstr_imm("smpp-tlv")); tlvs = gwlist_create(); tlvs_by_tag = dict_create(1024, (void(*)(void*))dict_destroy); tlvs_by_name = dict_create(1024, (void(*)(void*))dict_destroy); while (l != NULL && (grp = gwlist_extract_first(l)) != NULL) { struct smpp_tlv *tlv; Octstr *tmp, *smsc_id; List *l2; tlv = gw_malloc(sizeof(*tlv)); if ((tlv->name = cfg_get(grp, octstr_imm("name"))) == NULL) { error(0, "SMPP: Unable to get name for smpp-tlv."); smpp_tlv_destroy(tlv); goto failed; } if (cfg_get_integer(&tlv->tag, grp, octstr_imm("tag")) == -1) { error(0, "SMPP: Unable to get tag for smpp-tlv."); smpp_tlv_destroy(tlv); goto failed; } if (cfg_get_integer(&tlv->length, grp, octstr_imm("length")) == -1) { error(0, "SMPP: Unable to get length for smpp-tlv."); smpp_tlv_destroy(tlv); goto failed; } if ((tmp = cfg_get(grp, octstr_imm("type"))) == NULL) { error(0, "SMPP: Unable to get type for smpp-tlv."); smpp_tlv_destroy(tlv); goto failed; } if (octstr_str_case_compare(tmp, "octetstring") == 0) tlv->type = SMPP_TLV_OCTETS; else if (octstr_str_case_compare(tmp, "nulterminated") == 0) tlv->type = SMPP_TLV_NULTERMINATED; else if (octstr_str_case_compare(tmp, "integer") == 0) tlv->type = SMPP_TLV_INTEGER; else { error(0, "SMPP: Unknown type for smpp-tlv: `%s'", octstr_get_cstr(tmp)); octstr_destroy(tmp); smpp_tlv_destroy(tlv); goto failed; } octstr_destroy(tmp); /* put to all TLVs */ gwlist_produce(tlvs, tlv); smsc_id = cfg_get(grp, octstr_imm("smsc-id")); if (smsc_id != NULL) { l2 = octstr_split(smsc_id, octstr_imm(";")); octstr_destroy(smsc_id); } else { l2 = gwlist_create(); gwlist_produce(l2, octstr_create(DEFAULT_SMSC_ID)); } while(l2 != NULL && (smsc_id = gwlist_extract_first(l2)) != NULL) { Dict *tmp_dict; debug("sms.smpp", 0, "adding smpp-tlv for smsc-id=%s", octstr_get_cstr(smsc_id)); tmp_dict = dict_get(tlvs_by_name, smsc_id); if (tmp_dict == NULL) { tmp_dict = dict_create(1024, NULL); dict_put(tlvs_by_name, smsc_id, tmp_dict); } /* put into dict */ if (!dict_put_once(tmp_dict, tlv->name, tlv)) { error(0, "SMPP: Double TLV name %s found.", octstr_get_cstr(tlv->name)); octstr_destroy(smsc_id); goto failed; } tmp_dict = dict_get(tlvs_by_tag, smsc_id); if (tmp_dict == NULL) { tmp_dict = dict_create(1024, NULL); dict_put(tlvs_by_tag, smsc_id, tmp_dict); } tmp = octstr_format("%ld", tlv->tag); if (!dict_put_once(tmp_dict, tmp, tlv)) { error(0, "SMPP: Double TLV tag %s found.", octstr_get_cstr(tmp)); gwlist_destroy(l2, octstr_destroy_item); octstr_destroy(tmp); octstr_destroy(smsc_id); goto failed; } octstr_destroy(tmp); octstr_destroy(smsc_id); } gwlist_destroy(l2, octstr_destroy_item); } gwlist_destroy(l, NULL); initialized = 1; return 0; failed: gwlist_destroy(tlvs, (void(*)(void*))smpp_tlv_destroy); dict_destroy(tlvs_by_tag); dict_destroy(tlvs_by_name); return -1; }
static void udp_receiver(void *arg) { Octstr *datagram, *cliaddr; int ret; Msg *msg; Udpc *conn = arg; Octstr *ip; gwlist_add_producer(incoming_wdp); gwlist_add_producer(flow_threads); gwthread_wakeup(MAIN_THREAD_ID); /* remove messages from socket until it is closed */ while (1) { if (read_available(conn->fd, 100000) < 1) continue; ret = udp_recvfrom(conn->fd, &datagram, &cliaddr); if (ret == -1) { if (errno == EAGAIN) /* No datagram available, don't block. */ continue; error(errno, "Failed to receive an UDP"); continue; } ip = udp_get_ip(cliaddr); msg = msg_create(wdp_datagram); msg->wdp_datagram.source_address = udp_get_ip(cliaddr); msg->wdp_datagram.source_port = udp_get_port(cliaddr); msg->wdp_datagram.destination_address = udp_get_ip(conn->addr); msg->wdp_datagram.destination_port = udp_get_port(conn->addr); msg->wdp_datagram.user_data = datagram; info(0, "datagram received <%s:%d> -> <%s:%d>", octstr_get_cstr(udp_get_ip(cliaddr)), udp_get_port(cliaddr), octstr_get_cstr(udp_get_ip(conn->addr)), udp_get_port(conn->addr)); dump(msg); /* * Descide if this is (a) or (b) UDP packet and add them to the * corresponding queues */ if (octstr_compare(conn->addr, conn->map_addr) == 0) { gwlist_produce(incoming_wdp, msg); counter_increase(incoming_wdp_counter); } else { gwlist_produce(outgoing_wdp, msg); counter_increase(outgoing_wdp_counter); } octstr_destroy(cliaddr); octstr_destroy(ip); } gwlist_remove_producer(incoming_wdp); gwlist_remove_producer(flow_threads); }
void wsp_push_client_dispatch_event(WAPEvent *e) { gwlist_produce(push_client_queue, e); }
void wtls_dispatch_event(WAPEvent * event) { /* Stick the event on the incoming events queue */ gwlist_produce(wtls_queue, event); }
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); }
void wtp_initiator_dispatch_event(WAPEvent *event) { gwlist_produce(queue, event); }
static Boxc *route_msg(List *route_info, Msg *msg) { AddrPar *ap; Boxc *conn, *best; int i, b, len; ap = gwlist_search(route_info, msg, cmp_route); if (ap == NULL) { debug("bb.boxc", 0, "Did not find previous routing info for WDP, " "generating new"); route: if (gwlist_len(wapbox_list) == 0) return NULL; gwlist_lock(wapbox_list); /* take random wapbox from list, and then check all wapboxes * and select the one with lowest load level - if tied, the first * one */ len = gwlist_len(wapbox_list); b = gw_rand() % len; best = gwlist_get(wapbox_list, b); for(i = 0; i < gwlist_len(wapbox_list); i++) { conn = gwlist_get(wapbox_list, (i+b) % len); if (conn != NULL && best != NULL) if (conn->load < best->load) best = conn; } if (best == NULL) { warning(0, "wapbox_list empty!"); gwlist_unlock(wapbox_list); return NULL; } conn = best; conn->load++; /* simulate new client until we get new values */ ap = gw_malloc(sizeof(AddrPar)); ap->address = octstr_duplicate(msg->wdp_datagram.source_address); ap->port = msg->wdp_datagram.source_port; ap->wapboxid = conn->id; gwlist_produce(route_info, ap); gwlist_unlock(wapbox_list); } else conn = gwlist_search(wapbox_list, ap, cmp_boxc); if (conn == NULL) { /* routing failed; wapbox has disappeared! * ..remove routing info and re-route */ debug("bb.boxc", 0, "Old wapbox has disappeared, re-routing"); gwlist_delete_equal(route_info, ap); ap_destroy(ap); goto route; } return conn; }
/* runs over a single directory, running queue items. return -1 if failed to run some item. * each directory found is pushed onto stack for future processing. * dir must have trailing slash * return value of -2 means quit. */ static int run_dir(char *topdir, char *dir, struct Qthread_t *tlist, int num_threads, int *i, List *stack) { DIR *dirp; struct dirent *dp; Octstr *tdir = octstr_format("%s/%s", topdir, dir); char *xdir = octstr_get_cstr(tdir); int ret = 0; dirp = opendir(xdir); //debug("",0,"run_dir[%s] tlist=%p",octstr_get_cstr(tdir), tlist); if (!dirp) { error(0, "mms_queue_run: Failed to read queue directory %s, error=%s", xdir, strerror(errno)); ret = -1; goto done; } while ((dp = readdir(dirp)) != NULL) { struct stat st; Octstr *xfname = octstr_format("%s%s", xdir, dp->d_name); int sres = stat(octstr_get_cstr(xfname), &st); time_t tnow = time(NULL); octstr_destroy(xfname); if (sres == 0 && S_ISREG(st.st_mode) && dp->d_name[0] == MQF && dp->d_name[1] == 'f') { if (mms_queue_live_count() > max_live_queued) { if (!max_live_exceeded_warning_issued) warning(0, "Exceeded limit for new live requests while processing %s Currently I got %d queued in memory.", topdir, mms_queue_live_count()); max_live_exceeded_warning_issued = 1; break; } max_live_exceeded_warning_issued = 0; Octstr *xqf = xmake_qf(dp->d_name, dir); MmsEnvelope *e = mms_queue_readenvelope(octstr_get_cstr(xqf),topdir, 0); octstr_destroy(xqf); if (!e) continue; if (e->sendt <= tnow) { int queued = 0; int j = *i; /* This is the next thread to use. Checking for cycles. */ do { if (tlist[*i].l) { debug("queuerun", 0, "Queued to thread %d for %s%s, sendt=%d, tnow=%d", *i, xdir, dp->d_name, (int)e->sendt, (int)tnow); debug("queuerun", 0, "tlist[%d] = %p", *i, &tlist[*i]); gwlist_produce(tlist[*i].l, e); queued = 1; } *i = (*i+1)%num_threads; } while (!queued && *i != j); if (!queued) { /* A problem. There are no sender threads! */ free_envelope(e, 0); error(0, "mms_queue_run: No active sender queues for directory %s. Quiting.",xdir); ret = -2; break; } } else free_envelope(e,0); /* Let go of it. */ } else if (sres == 0 && S_ISDIR(st.st_mode) && strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0) { Octstr *newdir = octstr_format("%s%s/", dir, dp->d_name); gwlist_append(stack, newdir); /* push it... */ } } if (dirp) closedir(dirp); done: octstr_destroy(tdir); return ret; }
void mmsc_receive_func(MmscGrp *m) { int i; MmsBoxHTTPClientInfo h = {NULL}; List *mmsc_incoming_reqs = gwlist_create(); long *thids = gw_malloc((maxthreads + 1)*sizeof thids[0]); gwlist_add_producer(mmsc_incoming_reqs); for (i = 0; i<maxthreads; i++) thids[i] = gwthread_create((gwthread_func_t *)dispatch_mm7_recv, mmsc_incoming_reqs); h.m = m; while(rstop == 0 && (h.client = http_accept_request(m->incoming.port, &h.ip, &h.url, &h.headers, &h.body, &h.cgivars)) != NULL) if (is_allowed_ip(m->incoming.allow_ip, m->incoming.deny_ip, h.ip)) { MmsBoxHTTPClientInfo *hx = gw_malloc(sizeof hx[0]); h.ua = http_header_value(h.headers, octstr_imm("User-Agent")); *hx = h; debug("mmsbox", 0, " MM7 Incoming, IP=[%s], MMSC=[%s], dest_port=[%ld] ", h.ip ? octstr_get_cstr(h.ip) : "", octstr_get_cstr(m->id), m->incoming.port); /* Dump headers, url etc. */ #if 0 http_header_dump(h.headers); if (h.body) octstr_dump(h.body, 0); if (h.ip) octstr_dump(h.ip, 0); #endif gwlist_produce(mmsc_incoming_reqs, hx); } else { h.ua = http_header_value(h.headers, octstr_imm("User-Agent")); mms_error_ex("auth",0, "MM7", m->id, "HTTP: Incoming IP denied MMSC[%s] ip=[%s], ua=[%s], disconnected", m->id ? octstr_get_cstr(m->id) : "(none)", h.ip ? octstr_get_cstr(h.ip) : "(none)", h.ua ? octstr_get_cstr(h.ua) : "(none)"); http_send_reply(h.client, HTTP_FORBIDDEN, NULL, octstr_imm("Access denied.")); free_mmsbox_http_clientInfo(&h, 0); } debug("proxy", 0, "MMSBox: MM7 receiver [mmc=%s] Shutting down...", octstr_get_cstr(m->id)); gwlist_remove_producer(mmsc_incoming_reqs); for (i = 0; i<maxthreads; i++) if (thids[i] >= 0) gwthread_join(thids[i]); gwlist_destroy(mmsc_incoming_reqs, NULL); gw_free(thids); debug("proxy", 0, "MMSBox: MM7 receiver [mmc=%s] Shutting down complete.", octstr_get_cstr(m->id)); }
static void udp_receiver(void *arg) { Octstr *datagram, *cliaddr; int ret; Msg *msg; Udpc *conn = arg; Octstr *ip; gwlist_add_producer(incoming_wdp); gwlist_add_producer(flow_threads); gwthread_wakeup(MAIN_THREAD_ID); /* remove messages from socket until it is closed */ while (bb_status != BB_DEAD && bb_status != BB_SHUTDOWN) { gwlist_consume(isolated); /* block here if suspended/isolated */ if (read_available(conn->fd, 100000) < 1) continue; ret = udp_recvfrom(conn->fd, &datagram, &cliaddr); if (ret == -1) { if (errno == EAGAIN) /* No datagram available, don't block. */ continue; error(errno, "Failed to receive an UDP"); /* * just continue, or is there ANY error that would result * in situation where it would be better to break; or even * die off? - Kalle 28.2 */ continue; } /* discard the message if the client is not allowed */ ip = udp_get_ip(cliaddr); if (!is_allowed_ip(allow_ip, deny_ip, ip)) { warning(0, "UDP: Discarding packet from %s, IP is denied.", octstr_get_cstr(ip)); octstr_destroy(datagram); } else { debug("bb.udp", 0, "datagram received"); msg = msg_create(wdp_datagram); msg->wdp_datagram.source_address = udp_get_ip(cliaddr); msg->wdp_datagram.source_port = udp_get_port(cliaddr); msg->wdp_datagram.destination_address = udp_get_ip(conn->addr); msg->wdp_datagram.destination_port = udp_get_port(conn->addr); msg->wdp_datagram.user_data = datagram; gwlist_produce(incoming_wdp, msg); counter_increase(incoming_wdp_counter); } octstr_destroy(cliaddr); octstr_destroy(ip); } gwlist_remove_producer(incoming_wdp); gwlist_remove_producer(flow_threads); }
void wsp_session_dispatch_event(WAPEvent *event) { wap_event_assert(event); gwlist_produce(queue, event); }
void wap_push_ota_dispatch_event(WAPEvent *e) { gw_assert(run_status == running); gwlist_produce(ota_queue, e); }