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 int store_file_dump(void) { int retval; debug("bb.store", 0, "Dumping %ld messages to store", dict_key_count(sms_dict)); mutex_lock(file_mutex); if (file != NULL) { fclose(file); file = NULL; } retval = do_dump(); mutex_unlock(file_mutex); return retval; }
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); }
Octstr *boxc_status(int status_type) { Octstr *tmp; char *lb, *ws; int i, boxes, para = 0; time_t orig, t; Boxc *bi; orig = time(NULL); /* * XXX: this will cause segmentation fault if this is called * between 'destroy_list and setting list to NULL calls. * Ok, this has to be fixed, but now I am too tired. */ if ((lb = bb_status_linebreak(status_type))==NULL) return octstr_create("Un-supported format"); if (status_type == BBSTATUS_HTML) ws = " "; else if (status_type == BBSTATUS_TEXT) ws = " "; else ws = ""; if (status_type == BBSTATUS_HTML || status_type == BBSTATUS_WML) para = 1; if (status_type == BBSTATUS_XML) { tmp = octstr_create (""); octstr_append_cstr(tmp, "<boxes>\n\t"); } else tmp = octstr_format("%sBox connections:%s", para ? "<p>" : "", lb); boxes = 0; if (wapbox_list) { gwlist_lock(wapbox_list); for(i=0; i < gwlist_len(wapbox_list); i++) { bi = gwlist_get(wapbox_list, i); if (bi->alive == 0) continue; t = orig - bi->connect_time; if (status_type == BBSTATUS_XML) octstr_format_append(tmp, "<box>\n\t\t<type>wapbox</type>\n\t\t<IP>%s</IP>\n" "\t\t<status>on-line %ldd %ldh %ldm %lds</status>\n" "\t\t<ssl>%s</ssl>\n\t</box>\n", octstr_get_cstr(bi->client_ip), t/3600/24, t/3600%24, t/60%60, t%60, #ifdef HAVE_LIBSSL conn_get_ssl(bi->conn) != NULL ? "yes" : "no" #else "not installed" #endif ); else octstr_format_append(tmp, "%swapbox, IP %s (on-line %ldd %ldh %ldm %lds) %s %s", ws, octstr_get_cstr(bi->client_ip), t/3600/24, t/3600%24, t/60%60, t%60, #ifdef HAVE_LIBSSL conn_get_ssl(bi->conn) != NULL ? "using SSL" : "", #else "", #endif lb); boxes++; } gwlist_unlock(wapbox_list); } if (smsbox_list) { gw_rwlock_rdlock(smsbox_list_rwlock); for(i=0; i < gwlist_len(smsbox_list); i++) { bi = gwlist_get(smsbox_list, i); if (bi->alive == 0) continue; t = orig - bi->connect_time; if (status_type == BBSTATUS_XML) octstr_format_append(tmp, "<box>\n\t\t<type>smsbox</type>\n" "\t\t<id>%s</id>\n\t\t<IP>%s</IP>\n" "\t\t<queue>%ld</queue>\n" "\t\t<status>on-line %ldd %ldh %ldm %lds</status>\n" "\t\t<ssl>%s</ssl>\n\t</box>", (bi->boxc_id ? octstr_get_cstr(bi->boxc_id) : ""), octstr_get_cstr(bi->client_ip), gwlist_len(bi->incoming) + dict_key_count(bi->sent), t/3600/24, t/3600%24, t/60%60, t%60, #ifdef HAVE_LIBSSL conn_get_ssl(bi->conn) != NULL ? "yes" : "no" #else "not installed" #endif ); else octstr_format_append(tmp, "%ssmsbox:%s, IP %s (%ld queued), (on-line %ldd %ldh %ldm %lds) %s %s", ws, (bi->boxc_id ? octstr_get_cstr(bi->boxc_id) : "(none)"), octstr_get_cstr(bi->client_ip), gwlist_len(bi->incoming) + dict_key_count(bi->sent), t/3600/24, t/3600%24, t/60%60, t%60, #ifdef HAVE_LIBSSL conn_get_ssl(bi->conn) != NULL ? "using SSL" : "", #else "", #endif lb); boxes++; } gw_rwlock_unlock(smsbox_list_rwlock); } if (boxes == 0 && status_type != BBSTATUS_XML) { octstr_destroy(tmp); tmp = octstr_format("%sNo boxes connected", para ? "<p>" : ""); } if (para) octstr_append_cstr(tmp, "</p>"); if (status_type == BBSTATUS_XML) octstr_append_cstr(tmp, "</boxes>\n"); else octstr_append_cstr(tmp, "\n\n"); return tmp; }
static void proxy_thread(void *arg) { int ss, cs; /* server and client sockets */ int fl; /* socket flags */ Octstr *addr = NULL; int forward; Octstr *tmp; run_thread = 1; ss = cs = -1; /* create client binding, only if we have a remote server * and make the client socet non-blocking */ if (remote_host != NULL) { cs = udp_client_socket(); fl = fcntl(cs, F_GETFL); fcntl(cs, F_SETFL, fl | O_NONBLOCK); addr = udp_create_address(remote_host, remote_port); } /* create server binding */ ss = udp_bind(our_port, octstr_get_cstr(our_host)); /* make the server socket non-blocking */ fl = fcntl(ss, F_GETFL); fcntl(ss, F_SETFL, fl | O_NONBLOCK); if (ss == -1) panic(0, "RADIUS: Couldn't set up server socket for port %ld.", our_port); while (run_thread) { RADIUS_PDU *pdu, *r; Octstr *data, *rdata; Octstr *from_nas, *from_radius; pdu = r = NULL; data = rdata = from_nas = from_radius = NULL; if (read_available(ss, 100000) < 1) continue; /* get request from NAS */ if (udp_recvfrom(ss, &data, &from_nas) == -1) { if (errno == EAGAIN) /* No datagram available, don't block. */ continue; error(0, "RADIUS: Couldn't receive request data from NAS"); continue; } tmp = udp_get_ip(from_nas); info(0, "RADIUS: Got data from NAS <%s:%d>", octstr_get_cstr(tmp), udp_get_port(from_nas)); octstr_destroy(tmp); octstr_dump(data, 0); /* unpacking the RADIUS PDU */ if ((pdu = radius_pdu_unpack(data)) == NULL) { warning(0, "RADIUS: Couldn't unpack PDU from NAS, ignoring."); goto error; } info(0, "RADIUS: from NAS: PDU type: %s", pdu->type_name); /* authenticate the Accounting-Request packet */ if (radius_authenticate_pdu(pdu, &data, secret_nas) == 0) { warning(0, "RADIUS: Authentication failed for PDU from NAS, ignoring."); goto error; } /* store to hash table if not present yet */ mutex_lock(radius_mutex); forward = update_tables(pdu); mutex_unlock(radius_mutex); /* create response PDU for NAS */ r = radius_pdu_create(0x05, pdu); /* * create response authenticator * code+identifier(req)+length+authenticator(req)+(attributes)+secret */ r->u.Accounting_Response.identifier = pdu->u.Accounting_Request.identifier; r->u.Accounting_Response.authenticator = octstr_duplicate(pdu->u.Accounting_Request.authenticator); /* pack response for NAS */ rdata = radius_pdu_pack(r); /* creates response autenticator in encoded PDU */ radius_authenticate_pdu(r, &rdata, secret_nas); /* * forward request to remote RADIUS server only if updated * and if we have a configured remote RADIUS server */ if ((remote_host != NULL) && forward) { if (udp_sendto(cs, data, addr) == -1) { error(0, "RADIUS: Couldn't send to remote RADIUS <%s:%ld>.", octstr_get_cstr(remote_host), remote_port); } else if (read_available(cs, remote_timeout) < 1) { error(0, "RADIUS: Timeout for response from remote RADIUS <%s:%ld>.", octstr_get_cstr(remote_host), remote_port); } else if (udp_recvfrom(cs, &data, &from_radius) == -1) { error(0, "RADIUS: Couldn't receive from remote RADIUS <%s:%ld>.", octstr_get_cstr(remote_host), remote_port); } else { info(0, "RADIUS: Got data from remote RADIUS <%s:%d>.", octstr_get_cstr(udp_get_ip(from_radius)), udp_get_port(from_radius)); octstr_dump(data, 0); /* XXX unpack the response PDU and check if the response * authenticator is valid */ } } /* send response to NAS */ if (udp_sendto(ss, rdata, from_nas) == -1) error(0, "RADIUS: Couldn't send response data to NAS <%s:%d>.", octstr_get_cstr(udp_get_ip(from_nas)), udp_get_port(from_nas)); error: radius_pdu_destroy(pdu); radius_pdu_destroy(r); octstr_destroy(rdata); octstr_destroy(data); octstr_destroy(from_nas); debug("radius.proxy", 0, "RADIUS: Mapping table contains %ld elements", dict_key_count(radius_table)); debug("radius.proxy", 0, "RADIUS: Session table contains %ld elements", dict_key_count(session_table)); debug("radius.proxy", 0, "RADIUS: Client table contains %ld elements", dict_key_count(client_table)); } octstr_destroy(addr); }
static int store_file_load(void(*receive_msg)(Msg*)) { List *keys; Octstr *store_file, *key; Msg *msg; int retval, msgs; long end, pos; if (filename == NULL) return 0; mutex_lock(file_mutex); if (file != NULL) { fclose(file); file = NULL; } store_file = octstr_read_file(octstr_get_cstr(filename)); if (store_file != NULL) info(0, "Loading store file `%s'", octstr_get_cstr(filename)); else { store_file = octstr_read_file(octstr_get_cstr(newfile)); if (store_file != NULL) info(0, "Loading store file `%s'", octstr_get_cstr(newfile)); else { store_file = octstr_read_file(octstr_get_cstr(bakfile)); if (store_file != NULL) info(0, "Loading store file `%s'", octstr_get_cstr(bakfile)); else { info(0, "Cannot open any store file, starting a new one"); retval = open_file(filename); goto end; } } } info(0, "Store-file size %ld, starting to unpack%s", octstr_len(store_file), octstr_len(store_file) > 10000 ? " (may take awhile)" : ""); pos = 0; msgs = 0; end = octstr_len(store_file); while (pos < end) { if (read_msg(&msg, store_file, &pos) == -1) { error(0, "Garbage at store-file, skipped."); continue; } if (msg_type(msg) == sms) { store_to_dict(msg); msgs++; } else if (msg_type(msg) == ack) { store_to_dict(msg); } else { warning(0, "Strange message in store-file, discarded, " "dump follows:"); msg_dump(msg, 0); } msg_destroy(msg); } octstr_destroy(store_file); info(0, "Retrieved %d messages, non-acknowledged messages: %ld", msgs, dict_key_count(sms_dict)); /* now create a new sms_store out of messages left */ keys = dict_keys(sms_dict); while ((key = gwlist_extract_first(keys)) != NULL) { msg = dict_remove(sms_dict, key); if (store_to_dict(msg) != -1) { receive_msg(msg); } else { error(0, "Found unknown message type in store file."); msg_dump(msg, 0); msg_destroy(msg); } octstr_destroy(key); } gwlist_destroy(keys, octstr_destroy_item); /* Finally, generate new store file out of left messages */ retval = do_dump(); end: mutex_unlock(file_mutex); /* allow using of store */ gwlist_remove_producer(loaded); /* start dumper thread */ if ((cleanup_thread = gwthread_create(store_dumper, NULL))==-1) panic(0, "Failed to create a cleanup thread!"); return retval; }
static long store_file_messages(void) { return (sms_dict ? dict_key_count(sms_dict) : -1); }