Exemplo n.º 1
0
static int httpsmsc_shutdown(SMSCConn *conn, int finish_sending)
{
    ConnData *conndata = conn->data;

    if (conndata == NULL)
        return 0;

    debug("httpsmsc_shutdown", 0, "HTTP[%s]: Shutting down",
          octstr_get_cstr(conn->id));

    mutex_lock(conn->flow_mutex);
    conn->why_killed = SMSCCONN_KILLED_SHUTDOWN;

    conndata->shutdown = 1;

    if (conndata->port > 0)
        http_close_port(conndata->port);
    gwlist_remove_producer(conndata->msg_to_send);
    if (conndata->receive_thread != -1)
        gwthread_wakeup(conndata->receive_thread);
    if (conndata->sender_thread != -1)
        gwthread_wakeup(conndata->sender_thread);
    mutex_unlock(conn->flow_mutex);

    return 0;
}
Exemplo n.º 2
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);
}
Exemplo n.º 3
0
static int shutdown_cb(SMSCConn *conn, int finish_sending)
{
    PrivData *privdata = conn->data;

    debug("bb.sms", 0, "Shutting down SMSCConn FAKE, %s",
          finish_sending ? "slow" : "instant");

    /* 
     * Documentation claims this would have been done by smscconn.c,
     * but isn't when this code is being written. 
     */
    conn->why_killed = SMSCCONN_KILLED_SHUTDOWN;
    privdata->shutdown = 1; 
    /*
     * Separate from why_killed to avoid locking, as
     * why_killed may be changed from outside? 
     */

    if (finish_sending == 0) {
        Msg *msg;
        while((msg = gwlist_extract_first(privdata->outgoing_queue)) != NULL) {
            bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_SHUTDOWN, NULL);
        }
    }

    gwthread_wakeup(privdata->connection_thread);
    return 0;
}
Exemplo n.º 4
0
void timers_shutdown(void)
{
    if (initialized > 1) {
        initialized--;
        return;
    }
       
    /* Stop all timers. */
    if (timers->heap->len > 0)
        warning(0, "Timers shutting down with %ld active timers.",
                timers->heap->len);
    while (timers->heap->len > 0)
        gwtimer_stop(timers->heap->tab[0]);

    /* Kill timer thread */
    timers->stopping = 1;
    gwthread_wakeup(timers->thread);
    gwthread_join(timers->thread);

    initialized = 0;

    /* Free resources */
    heap_destroy(timers->heap);
    mutex_destroy(timers->mutex);
    gw_free(timers);
}
Exemplo n.º 5
0
static int add_msg_cb(SMSCConn *conn, Msg *sms)
{
    PrivData *privdata = conn->data;
    Msg *copy;

    copy = msg_duplicate(sms);
  
    /*  
     * Send DLR if desired, which means first add the DLR entry 
     * and then later find it and remove it. We need to ensure
     * that we put the DLR in first before producing the copy
     * to the list.
     */
    if (DLR_IS_ENABLED_DEVICE(sms->sms.dlr_mask)) {
        Octstr *tmp;
        char id[UUID_STR_LEN + 1];
        uuid_unparse(sms->sms.id, id);
        tmp = octstr_format("%s", id);
        dlr_add(conn->id, tmp, sms, 0);
        octstr_destroy(tmp);
    }
    gwlist_produce(privdata->outgoing_queue, copy);

    gwthread_wakeup(privdata->connection_thread);

    return 0;
}
Exemplo n.º 6
0
static void start_cb(SMSCConn *conn)
{
    PrivData *privdata = conn->data;

    /* in case there are messages in the buffer already */
    gwthread_wakeup(privdata->connection_thread);
    debug("bb.sms", 0, "smsc_fake: start called");
}
Exemplo n.º 7
0
static void cgw_start_cb(SMSCConn *conn)
{
    PrivData *privdata = conn->data;

    /* in case there are messages in the buffer already */
    if (privdata->rport > 0)
        gwthread_wakeup(privdata->receiver_thread);
    debug("smsc.cgw", 0, "smsc_cgw: start called");
}
Exemplo n.º 8
0
static int wrapper_shutdown(SMSCConn *conn, int finish_sending)
{
    SmscWrapper *wrap = conn->data;

    debug("bb.sms", 0, "Shutting down SMSCConn %s, %s",
	  octstr_get_cstr(conn->name), finish_sending ? "slow" : "instant");
    
    if (finish_sending == 0) {
	Msg *msg; 
	while((msg = gwlist_extract_first(wrap->outgoing_queue))!=NULL) {
	    bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_SHUTDOWN, NULL);
	}
    }
    gwlist_remove_producer(wrap->outgoing_queue);
    gwthread_wakeup(wrap->sender_thread);
    gwthread_wakeup(wrap->receiver_thread);
    return 0;
}
Exemplo n.º 9
0
void gwthread_wakeup_all(void)
{
    long i;
    long our_thread = gwthread_self();

    for (i = 0; i < THREADTABLE_SIZE; ++i) {
        if (THREAD(our_thread) != THREAD(i))
            gwthread_wakeup(i);
    }
}
Exemplo n.º 10
0
static int cgw_add_msg_cb(SMSCConn *conn, Msg *sms)
{
    PrivData *privdata = conn->data;
    Msg *copy;

    copy = msg_duplicate(sms);
    gwlist_produce(privdata->outgoing_queue, copy);
    gwthread_wakeup(privdata->sender_thread);

    return 0;
}
Exemplo n.º 11
0
static Octstr *httpd_shutdown(List *cgivars, int status_type)
{
    Octstr *reply;
    if ((reply = httpd_check_authorization(cgivars, 0))!= NULL) return reply;
    if (bb_status == BB_SHUTDOWN)
	bb_status = BB_DEAD;
    else {
	bb_shutdown();
        gwthread_wakeup(MAIN_THREAD_ID);
    }
    return octstr_create("Bringing system down");
}
Exemplo n.º 12
0
static void store_file_shutdown(void)
{
    if (filename == NULL)
        return;

    active = 0;
    gwthread_wakeup(cleanup_thread);
    /* wait for cleanup thread */
    if (cleanup_thread != -1)
        gwthread_join(cleanup_thread);

    gwlist_destroy(loaded, NULL);
}
Exemplo n.º 13
0
void gw_timer_elapsed_start(Timer *timer, int interval, void *data)
{
    int wakeup = 0;

    gw_assert(timer != NULL);

    if (timer == NULL)
        return;

    lock(timer->timerset);

    /* Convert to absolute time */
    interval += time(NULL);

    if (timer->elapses > 0) {
        /* Resetting an existing timer.  Move it to its new
         * position in the heap. */
        if (interval < timer->elapses && timer->index == 0)
            wakeup = 1;
        timer->elapses = interval;
        gw_assert(timer->index >= 0);
        gw_assert(timer->timerset->heap->tab[timer->index] == timer);
        wakeup |= heap_adjust(timer->timerset->heap, timer->index);
    } else {
        /* Setting a new timer, or resetting an elapsed one.
         * There should be no further elapse event on the
         * output list here. */
        /* abort_elapsed(timer); */
    	timer->elapsed_data = NULL;

        /* Then activate the timer. */
        timer->elapses = interval;
        gw_assert(timer->index < 0);
        heap_insert(timer->timerset->heap, timer);
        wakeup = timer->index == 0;  /* Do we have a new top? */
    }

    if (data != NULL) {
        timer->data = data;
    }

    unlock(timer->timerset);

    if (wakeup)
        gwthread_wakeup(timer->timerset->thread);
}
Exemplo n.º 14
0
void gwtimer_start(Timer *timer, int interval, WAPEvent *event)
{
    int wakeup = 0;

    gw_assert(initialized);
    gw_assert(timer != NULL);
    gw_assert(event != NULL || timer->event != NULL);

    lock(timers);

    /* Convert to absolute time */
    interval += time(NULL);

    if (timer->elapses > 0) {
        /* Resetting an existing timer.  Move it to its new
         * position in the heap. */
        if (interval < timer->elapses && timer->index == 0)
            wakeup = 1;
        timer->elapses = interval;
        gw_assert(timers->heap->tab[timer->index] == timer);
        wakeup |= heap_adjust(timers->heap, timer->index);
    } else {
        /* Setting a new timer, or resetting an elapsed one.
         * First deal with a possible elapse event that may
         * still be on the output list. */
        abort_elapsed(timer);

        /* Then activate the timer. */
        timer->elapses = interval;
        gw_assert(timer->index < 0);
        heap_insert(timers->heap, timer);
        wakeup = timer->index == 0;  /* Do we have a new top? */
    }

    if (event != NULL) {
	wap_event_destroy(timer->event);
	timer->event = event;
    }

    unlock(timers);

    if (wakeup)
        gwthread_wakeup(timers->thread);
}
Exemplo n.º 15
0
void gw_timerset_destroy(Timerset *set)
{
	if (set == NULL)
		return;
       
    /* Stop all timers. */
    while (set->heap->len > 0)
        gw_timer_stop(set->heap->tab[0]);

    /* Kill timer thread */
    set->stopping = 1;
    gwthread_wakeup(set->thread);
    gwthread_join(set->thread);

    /* Free resources */
    heap_destroy(set->heap);
    mutex_destroy(set->mutex);
    gw_free(set);
}
Exemplo n.º 16
0
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);
}
Exemplo n.º 17
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);
        }
    }
}
Exemplo n.º 18
0
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);
}
Exemplo n.º 19
0
static void wrapper_sender(void *arg)
{
    Msg 	*msg;
    SMSCConn 	*conn = arg;
    SmscWrapper *wrap = conn->data;

    /* Make sure we log into our own log-file if defined */
    log_thread_to(conn->log_idx);

    /* send messages to SMSC until our outgoing_list is empty and
     * no producer anymore (we are set to shutdown) */
    while(conn->status != SMSCCONN_DEAD) {

	if ((msg = gwlist_consume(wrap->outgoing_queue)) == NULL)
            break;

        if (octstr_search_char(msg->sms.receiver, ' ', 0) != -1) {
            /*
             * multi-send: this should be implemented in corresponding
             *  SMSC protocol, but while we are waiting for that...
             */
            int i;
	    Msg *newmsg;
            /* split from spaces: in future, split with something more sensible,
             * this is dangerous... (as space is url-encoded as '+')
             */
            List *nlist = octstr_split_words(msg->sms.receiver);

	    debug("bb.sms", 0, "Handling multi-receiver message");

            for(i=0; i < gwlist_len(nlist); i++) {

		newmsg = msg_duplicate(msg);
                octstr_destroy(newmsg->sms.receiver);

                newmsg->sms.receiver = gwlist_get(nlist, i);
                sms_send(conn, newmsg);
            }
            gwlist_destroy(nlist, NULL);
            msg_destroy(msg);
        }
        else
	    sms_send(conn,msg);

    }
    /* cleanup, we are now dying */

    debug("bb.sms", 0, "SMSCConn %s sender died, waiting for receiver",
	  octstr_get_cstr(conn->name));
    
    conn->why_killed = SMSCCONN_KILLED_SHUTDOWN;

    if (conn->is_stopped) {
	gwlist_remove_producer(wrap->stopped);
	conn->is_stopped = 0;
    }

    gwthread_wakeup(wrap->receiver_thread);
    gwthread_join(wrap->receiver_thread);

    /* call 'failed' to all messages still in queue */
    
    mutex_lock(conn->flow_mutex);

    conn->status = SMSCCONN_DEAD;

    while((msg = gwlist_extract_first(wrap->outgoing_queue))!=NULL) {
	bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_SHUTDOWN, NULL);
    }
    smscwrapper_destroy(wrap);
    conn->data = NULL;
    
    mutex_unlock(conn->flow_mutex);

    bb_smscconn_killed();
}
Exemplo n.º 20
0
/*
 * 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();
    }
}
Exemplo n.º 21
0
/*
 * Thread to listen to HTTP requests from SMSC entity
 */
static void httpsmsc_receiver(void *arg)
{
    SMSCConn *conn = arg;
    ConnData *conndata = conn->data;
    HTTPClient *client;
    Octstr *ip, *url, *body;
    List *headers, *cgivars;

    /* Make sure we log into our own log-file if defined */
    log_thread_to(conn->log_idx);

    while (conndata->shutdown == 0) {
        /* reset */
        ip = url = body = NULL;
        headers = cgivars = NULL;

        /* XXX if conn->is_stopped, do not receive new messages.. */

        client = http_accept_request(conndata->port, &ip, &url,
                                     &headers, &body, &cgivars);
        if (client == NULL)
            break;

        if (cgivars != NULL) {
        	octstr_append_char(url, '?');
        	http_cgivar_dump_into(cgivars, url);
        }

        debug("smsc.http", 0, "HTTP[%s]: Got request `%s'",
              octstr_get_cstr(conn->id), octstr_get_cstr(url));

        if (connect_denied(conndata->allow_ip, ip)) {
            info(0, "HTTP[%s]: Connection `%s' tried from denied "
                    "host %s, ignored", octstr_get_cstr(conn->id),
                    octstr_get_cstr(url), octstr_get_cstr(ip));
            http_close_client(client);
        } else
            conndata->callbacks->receive_sms(conn, client, headers, body, cgivars);

        debug("smsc.http", 0, "HTTP[%s]: Destroying client information",
              octstr_get_cstr(conn->id));
        octstr_destroy(url);
        octstr_destroy(ip);
        octstr_destroy(body);
        http_destroy_headers(headers);
        http_destroy_cgiargs(cgivars);
    }
    debug("smsc.http", 0, "HTTP[%s]: httpsmsc_receiver dying",
          octstr_get_cstr(conn->id));

    conndata->shutdown = 1;
    http_close_port(conndata->port);

    /* 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->sender_thread != -1) {
        gwthread_wakeup(conndata->sender_thread);
        gwthread_join(conndata->sender_thread);
    }
    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();
}
Exemplo n.º 22
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);
}
Exemplo n.º 23
0
static void cgw_listener(void *arg)
{
    SMSCConn	*conn = arg;
    PrivData	*privdata = conn->data;
    struct sockaddr_in server_addr;
    socklen_t	server_addr_len;
    Octstr	*ip;
    Connection	*server;
    int s, ret;

    /* Make sure we log into our own log-file if defined */
    log_thread_to(conn->log_idx);

    while (!privdata->shutdown) {
        server_addr_len = sizeof(server_addr);
	
        ret = gwthread_pollfd(privdata->listening_socket, POLLIN, -1);
        if (ret == -1) {
            if (errno == EINTR)
                continue;
            error(0, "Poll for cgw smsc connections failed, shutting down");
            break;
        }

        if (privdata->shutdown)
            break;
        if (ret == 0) /* This thread was woken up from elsewhere, but
                       * if we're not shutting down nothing to do here. */
            continue;
        s = accept(privdata->listening_socket, (struct sockaddr *) & server_addr,
                   &server_addr_len);
        if (s == -1) {
            warning(errno, "cgw_listener: accept() failed, retrying...");
            continue;
        }

        ip = host_ip(server_addr);
        if (!is_allowed_ip(privdata->allow_ip, privdata->deny_ip, ip)) {
            info(0, "CGW smsc connection tried from denied host <%s>, disconnected", octstr_get_cstr(ip));
            octstr_destroy(ip);
            close(s);
            continue;
        }
        server = conn_wrap_fd(s, 0);
        if (server == NULL) {
            error(0, "cgw_listener: conn_wrap_fd failed on accept()ed fd");
            octstr_destroy(ip);
            close(s);
            continue;
        }
        conn_claim(server);
        info(0, "cgw: smsc connected from %s", octstr_get_cstr(ip));
        octstr_destroy(ip);

        cgw_receiver(conn, server);
        conn_destroy(server);
    }
    if (close(privdata->listening_socket) == -1)
        warning(errno, "smsc_cgw: couldn't close listening socket at shutdown");
    gwthread_wakeup(privdata->sender_thread);
}
Exemplo n.º 24
0
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);
}