Exemple #1
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;
}
Exemple #2
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;
}
Exemple #3
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));
    }
}
Exemple #4
0
static void cgw_sender(void *arg)
{
    SMSCConn *conn = arg;
    PrivData *privdata = conn->data;
    Msg *msg = NULL;
    Connection *server = NULL;
    int l = 0;
    int ret = 0;

    conn->status = SMSCCONN_CONNECTING;

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

    while (!privdata->shutdown) {

        /* check that connection is active */
        if (conn->status != SMSCCONN_ACTIVE) {
            if ((server = cgw_open_send_connection(conn)) == NULL) {
                privdata->shutdown = 1;
                error(0, "Unable to connect to CGW server");
                return ;
            }

            conn->status = SMSCCONN_ACTIVE;
            bb_smscconn_connected(conn);
        } else {
	    ret = 0;
            l = gwlist_len(privdata->outgoing_queue);
            if (l > 0)
               ret = cgw_send_loop(conn, server);     /* send any messages in queue */

            if (ret != -1) ret = cgw_wait_command(privdata, conn, server, 1);     /* read ack's and delivery reports */
            if (ret != -1) cgw_check_acks(privdata);     /* check un-acked messages */
 
            if (ret == -1) {
                mutex_lock(conn->flow_mutex);
                conn->status = SMSCCONN_RECONNECTING;
                mutex_unlock(conn->flow_mutex);
	    }
        }
    }

    conn_destroy(server);

    while ((msg = gwlist_extract_first(privdata->outgoing_queue)) != NULL)
        bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_SHUTDOWN, NULL);
    mutex_lock(conn->flow_mutex);

    conn->status = SMSCCONN_DEAD;

    gwlist_destroy(privdata->outgoing_queue, NULL);
    octstr_destroy(privdata->host);
    octstr_destroy(privdata->allow_ip);
    octstr_destroy(privdata->deny_ip);

    gw_free(privdata);
    conn->data = NULL;

    mutex_unlock(conn->flow_mutex);
    debug("bb.sms", 0, "smsc_cgw connection has completed shutdown.");
    bb_smscconn_killed();
}
Exemple #5
0
static void fake_listener(void *arg)
{
    SMSCConn *conn = arg;
    PrivData *privdata = conn->data;
    struct sockaddr_in client_addr;
    socklen_t client_addr_len;
    Octstr *ip;
    Connection *client;
    int s, ret;
    Msg	*msg;

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

    while (1) {
        client_addr_len = sizeof(client_addr);
        ret = gwthread_pollfd(privdata->listening_socket, POLLIN, -1);
        if (ret == -1) {
            if (errno == EINTR)
                continue;
            error(0, "Poll for fakesmsc connections failed, shutting down");
            break;
        }
        if (privdata->shutdown)
            break;
        if (ret == 0) 
            /* 
             * This thread was woke up from elsewhere, but
             * if we're not shutting down nothing to do here. 
             */
            continue;
        s = accept(privdata->listening_socket, (struct sockaddr *)&client_addr,
                   &client_addr_len);
        if (s == -1) {
            warning(errno, "fake_listener: accept() failed, retrying...");
            continue;
        }
        ip = host_ip(client_addr);
        if (!is_allowed_ip(privdata->allow_ip, privdata->deny_ip, ip)) {
            info(0, "Fakesmsc connection tried from denied host <%s>, "
                    "disconnected", octstr_get_cstr(ip));
            octstr_destroy(ip);
            close(s);
            continue;
        }
        client = conn_wrap_fd(s, 0);
        if (client == NULL) {
            error(0, "fake_listener: conn_wrap_fd failed on accept()ed fd");
            octstr_destroy(ip);
            close(s);
            continue;
        }
        conn_claim(client);
        info(0, "Fakesmsc client connected from %s", octstr_get_cstr(ip));
        octstr_destroy(ip);
        mutex_lock(conn->flow_mutex);
        conn->status = SMSCCONN_ACTIVE;
        conn->connect_time = time(NULL);
        mutex_unlock(conn->flow_mutex);
        bb_smscconn_connected(conn);

        main_connection_loop(conn, client);

        if (privdata->shutdown)
            break;
        mutex_lock(conn->flow_mutex);
        conn->status = SMSCCONN_RECONNECTING;
        mutex_unlock(conn->flow_mutex);
        while ((msg = gwlist_extract_first(privdata->outgoing_queue)) != NULL) {
            bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_TEMPORARILY, NULL);
        }
    }
    if (close(privdata->listening_socket) == -1)
        warning(errno, "smsc_fake: couldn't close listening socket at shutdown");
    mutex_lock(conn->flow_mutex);

    conn->status = SMSCCONN_DEAD;

    while ((msg = gwlist_extract_first(privdata->outgoing_queue)) != NULL) {
        bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_SHUTDOWN, NULL);
    }
    gwlist_destroy(privdata->outgoing_queue, NULL);
    octstr_destroy(privdata->allow_ip);
    octstr_destroy(privdata->deny_ip);
    gw_free(privdata);
    conn->data = NULL;

    mutex_unlock(conn->flow_mutex);
    debug("bb.sms", 0, "smsc_fake connection has completed shutdown.");
    bb_smscconn_killed();
}