Example #1
0
static void main_for_list_add_and_delete(void) {
	static char *items[] = {
		"one",
		"two",
		"three",
	};
	int num_items = sizeof(items) / sizeof(items[0]);
	int num_repeats = 3;
	int i, j;
	char *p;
	List *list;

	list = gwlist_create();
	
	for (j = 0; j < num_repeats; ++j)
		for (i = 0; i < num_items; ++i)
			gwlist_append(list, items[i]);
	gwlist_delete_matching(list, items[0], compare_cstr);
	for (i = 0; i < gwlist_len(list); ++i) {
		p = gwlist_get(list, i);
		if (strcmp(p, items[0]) == 0)
			panic(0, "list contains `%s' after deleting it!",
				items[0]);
	}
	
	for (i = 0; i < num_items; ++i)
		gwlist_delete_equal(list, items[i]);
	if (gwlist_len(list) != 0)
		panic(0, "list is not empty after deleting everything");
	
	gwlist_destroy(list, NULL);
}
Example #2
0
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);
}
Example #3
0
/*
 * Go back and remove this timer's elapse event from the output list,
 * to pretend that it didn't elapse after all.  This is necessary
 * to deal with some races between the timer thread and the caller's
 * start/stop actions.
 */
static void abort_elapsed(Timer *timer)
{
    if (timer->elapsed_data == NULL)
        return;

    if (timer->output != NULL)
        gwlist_delete_equal(timer->output, timer->elapsed_data);
    timer->elapsed_data = NULL;
}
Example #4
0
static void push_client_machine_destroy(void *a) 
{
    WSPPushClientMachine *m;

    m = a;
    debug("wap.wsp", 0, "Destroying WSPPushClientMachine %p", (void *) m);
    gwlist_delete_equal(push_client_machines, m); 

    #define INTEGER(name) m->name = 0;
    #define HTTPHEADERS(name) http_destroy_headers(m->name);  
    #define MACHINE(fields) fields;
    #include "wsp_push_client_machine.def"

    gw_free(m);
}
Example #5
0
/*
 * Go back and remove this timer's elapse event from the output list,
 * to pretend that it didn't elapse after all.  This is necessary
 * to deal with some races between the timer thread and the caller's
 * start/stop actions.
 */
static void abort_elapsed(Timer *timer)
{
    long count;

    if (timer->elapsed_event == NULL)
        return;

    count = gwlist_delete_equal(timer->output, timer->elapsed_event);
    if (count > 0) {
        debug("timers", 0, "Aborting %s timer.",
              wap_event_name(timer->elapsed_event->type));
        wap_event_destroy(timer->elapsed_event);
    }
    timer->elapsed_event = NULL;
}
Example #6
0
static void machine_destroy(void *pp) {
	WSPMachine *p;
	
	p = pp;
	debug("wap.wsp", 0, "Destroying WSPMachine %p", pp);
	gwlist_delete_equal(session_machines, p);

	#define INTEGER(name) p->name = 0;
	#define OCTSTR(name) octstr_destroy(p->name);
	#define HTTPHEADERS(name) http_destroy_headers(p->name);
	#define ADDRTUPLE(name) wap_addr_tuple_destroy(p->name);
	#define MACHINESLIST(name) destroy_##name(p->name);
	#define CAPABILITIES(name) wsp_cap_destroy_list(p->name);
	#define COOKIES(name) cookies_destroy(p->name);
	#define REFERER(name) octstr_destroy(p->name);
	#define MACHINE(fields) fields
	#include "wsp_server_session_machine.def"
	gw_free(p);
}
Example #7
0
/*
 * Destroys a WTPInitMachine. Assumes it is safe to do so. Assumes it has 
 * already been deleted from the machines list.
 */
static void init_machine_destroy(void *p)
{
     WTPInitMachine *init_machine;

     init_machine = p;
     debug("wap.wtp", 0, "WTP: Destroying WTPInitMachine %p (%ld)", 
	    (void *) init_machine, init_machine->mid);
	
     gwlist_delete_equal(init_machines, init_machine);
        
     #define ENUM(name) init_machine->name = INITIATOR_NULL_STATE;
     #define INTEGER(name) init_machine->name = 0; 
     #define EVENT(name) wap_event_destroy(init_machine->name); 
     #define TIMER(name) gwtimer_destroy(init_machine->name); 
     #define ADDRTUPLE(name) wap_addr_tuple_destroy(init_machine->name); 
     #define MACHINE(field) field
     #include "wtp_init_machine.def"
     gw_free(init_machine);
}
Example #8
0
/*
 * Destroys a WTLSMachine. Assumes it is safe to do so. Assumes it has 
 * already been deleted from the machines list.
 */
static void wtls_machine_destroy(void *p)
{
       WTLSMachine *wtls_machine;

       wtls_machine = p;
   debug("wap.wtls", 0, "WTLS: Destroying WTLSMachine %ld (0x%p)",
         wtls_machine->mid, (void *)wtls_machine);
       gwlist_delete_equal(wtls_machines, wtls_machine);        
        
#define MACHINE(field) field
#define ENUM(name) wtls_machine->name = NULL_STATE;
#define ADDRTUPLE(name) wap_addr_tuple_destroy(wtls_machine->name);
#define INTEGER(name) wtls_machine->name = 0;
#define OCTSTR(name) octstr_destroy(wtls_machine->name);
#define PDULIST(name) wtls_machine->name = NULL;
#include "wtls_machine-decl.h"

        gw_free(wtls_machine);
}
Example #9
0
/* This function does NOT consume its event; it leaves that task up
 * to the parent session */
static void handle_method_event(WSPMachine *sm, WSPMethodMachine *msm, 
WAPEvent *current_event, WSP_PDU *pdu) {

	if (msm == NULL) {
		warning(0, "No method machine for event.");
		wap_event_dump(current_event);
		return;
	}
		
	debug("wap.wsp", 0, "WSP: method %ld, state %s, event %s",
		msm->transaction_id, state_name(msm->state), 
		wap_event_name(current_event->type));

	gw_assert(sm->session_id == msm->session_id);

	#define STATE_NAME(name)
	#define ROW(state_name, event, condition, action, next_state) \
		{ \
			struct event *e; \
			e = &current_event->u.event; \
			if (msm->state == state_name && \
			   current_event->type == event && \
			   (condition)) { \
				action \
				msm->state = next_state; \
				debug("wap.wsp", 0, "WSP %ld/%ld: New method state %s", \
					msm->session_id, msm->transaction_id, #next_state); \
				goto end; \
			} \
		}
	#include "wsp_server_method_states.def"
	
	cant_handle_event(sm, current_event);

end:
	if (msm->state == NULL_METHOD) {
		method_machine_destroy(msm);
		gwlist_delete_equal(sm->methodmachines, msm);
	}
}
Example #10
0
static void handle_push_event(WSPMachine *sm, WSPPushMachine *pm, 
                              WAPEvent *current_event)
{
        if (pm == NULL) {
		warning(0, "No push machine for event.");
		wap_event_dump(current_event);
		return;
	}

        debug("wap.wsp", 0, "WSP(tid/pid): push %ld/%ld, state %s, event %s",
		pm->transaction_id, pm->server_push_id, state_name(pm->state), 
		wap_event_name(current_event->type));
	gw_assert(sm->session_id == pm->session_id);

        #define STATE_NAME(name)
	#define ROW(state_name, event, condition, action, next_state) \
		{ \
		    if (pm->state == state_name && \
			current_event->type == event && \
			(condition)) { \
			     action \
			     pm->state = next_state; \
			     debug("wap.wsp", 0, "WSP %ld/%ld: New push state %s", \
			           pm->session_id, pm->transaction_id, #next_state); \
				goto end; \
			} \
		}
	#include "wsp_server_push_states.def"

        cant_handle_event(sm, current_event);
end:
        if (pm->state == SERVER_PUSH_NULL_STATE) {
		push_machine_destroy(pm);
		gwlist_delete_equal(sm->pushmachines, pm);
	}
}
Example #11
0
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;
}
Example #12
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);
}