Exemple #1
0
static void wait_for_connections(int fd, void (*function) (void *arg),
                                 List *waited)
{
    int ret;
    int timeout = 10; /* 10 sec. */

    gw_assert(function != NULL);

    while(sqlbox_status == SQL_RUNNING) {

        ret = gwthread_pollfd(fd, POLLIN, 1.0);
        if (sqlbox_status == SQL_SHUTDOWN) {
            if (ret == -1 || !timeout)
                    break;
                else
                    timeout--;
        }

        if (ret > 0) {
            gwthread_create(function, (void *)fd);
            gwthread_sleep(1.0);
        } else if (ret < 0) {
            if(errno==EINTR) continue;
            if(errno==EAGAIN) continue;
            error(errno, "wait_for_connections failed");
        }
    }
}
Exemple #2
0
static void accept_thread(void *arg)
{
    int fd;
    int new_fd;
    int port;
    socklen_t addrlen;
    struct sockaddr addr;
    long smsbox_thread_id;
    
    port = *(int *) arg;
    fd = make_server_socket(port, NULL);
    if (fd == -1)
    	panic(0, "Couldn't create SMPP listen port.");
    
    smsbox_thread_id = -1;
    for (;;) {
	if (gwthread_pollfd(fd, POLLIN, -1.0) != POLLIN)
	    break;
	addrlen = sizeof(addr);
	new_fd = accept(fd, &addr, &addrlen);
    	if (start_time == (time_t) -1)
	    time(&start_time);
	gwthread_create(receive_smpp_thread, 
			esme_create(conn_wrap_fd(new_fd, 0)));
	if (smsbox_thread_id == -1)
	    smsbox_thread_id = gwthread_create(smsbox_thread, NULL);
    }
    
    debug("test.smpp", 0, "%s terminates.", __func__);
}
Exemple #3
0
int conn_flush(Connection *conn)
{
    int ret;
    int revents;
    int fd;

    lock_out(conn);
    ret = unlocked_write(conn);
    if (ret < 0) {
        unlock_out(conn);
        return -1;
    }

    while (unlocked_outbuf_len(conn) != 0) {
        fd = conn->fd;

        unlock_out(conn);
        revents = gwthread_pollfd(fd, POLLOUT, -1.0);

        /* Note: Make sure we have the "out" lock when
         * going through the loop again, because the 
         * loop condition needs it. */

        if (revents < 0) {
            if (errno == EINTR)
                return 1;
            error(0, "conn_flush: poll failed on fd %d:", fd);
            return -1;
        }

        if (revents == 0) {
            /* We were woken up */
            return 1;
        }

        if (revents & POLLNVAL) {
            error(0, "conn_flush: fd %d not open.", fd);
            return -1;
        }

        lock_out(conn);

        if (revents & (POLLOUT | POLLERR | POLLHUP)) {
            ret = unlocked_write(conn);
            if (ret < 0) {
                unlock_out(conn);
                return -1;
            }
        }
    }

    unlock_out(conn);

    return 0;
}
Exemple #4
0
int gw_accept(int fd, Octstr **client_addr)
{
    struct sockaddr_in addr;
    socklen_t addrlen;
    int new_fd;

    if (gwthread_pollfd(fd, POLLIN, -1.0) != POLLIN) {
	debug("gwlib.socket", 0, "gwthread_pollfd interrupted or failed");
	return -1;
    }
    addrlen = sizeof(addr);
    new_fd = accept(fd, (struct sockaddr *) &addr, &addrlen);
    if (new_fd == -1) {
	error(errno, "accept system call failed.");
	return -1;
    }
    *client_addr = host_ip(addr);
    debug("test_smsc", 0, "accept() succeeded, client from %s",
	  octstr_get_cstr(*client_addr));
    return new_fd;
}
Exemple #5
0
static void wait_for_connections(int fd, void (*function) (void *arg), 
    	    	    	    	 List *waited, int ssl)
{
    int ret;
    int timeout = 10; /* 10 sec. */

    gw_assert(function != NULL);
    
    while(bb_status != BB_DEAD) {

        /* if we are being shutdowned, as long as there is
         * messages in incoming list allow new connections, but when
         * list is empty, exit.
         * Note: We have timeout (defined above) for which we allow new connections.
         *           Otherwise we wait here for ever!
         */
        if (bb_status == BB_SHUTDOWN) {
            ret = gwlist_wait_until_nonempty(waited);
            if (ret == -1 || !timeout)
                break;
            else
                timeout--;
        }

        /* block here if suspended */
        gwlist_consume(suspended);

        ret = gwthread_pollfd(fd, POLLIN, 1.0);
        if (ret > 0) {
            Boxc *newconn = accept_boxc(fd, ssl);
            if (newconn != NULL) {
                gwthread_create(function, newconn);
                gwthread_sleep(1.0);
            } else {
                error(0, "Failed to create new boxc connection.");
            }
        } else if (ret < 0 && errno != EINTR && errno != EAGAIN)
            error(errno, "bb_boxc::wait_for_connections failed");
    }
}
Exemple #6
0
int cgw_wait_command(PrivData *privdata, SMSCConn *conn, Connection *server, int timeout)
{
    int ret;
    struct cgwop *cgwop;

    /* is there data to be read? */
    ret = gwthread_pollfd(privdata->send_socket, POLLIN, 0.2); 
    
    if (ret != -1) {
        /* read all waiting ops */
	cgwop = cgw_read_op(privdata, conn, server, timeout);
        if (cgwop != NULL) {
	    do {
		if (conn_eof(server)) {
		    info(0, "cgw: Connection closed by SMSC");
		    conn->status = SMSCCONN_DISCONNECTED;
		    if (cgwop != NULL) cgwop_destroy(cgwop);
		    return -1;
		}
		if (conn_error(server)) {
		    error(0, "cgw: Error trying to read ACKs from SMSC");
		    if (cgwop != NULL) cgwop_destroy(cgwop);
		    return -1;
		}

		cgw_handle_op(conn, server, cgwop);
		cgwop_destroy(cgwop);
	    } while ((cgwop = cgw_read_op(privdata, conn, server, timeout)) != NULL);
	} else 
	    conn_wait(server, 1); /* added because gwthread_pollfd
				     seems to always return 1. This will keep
				     the load on a reasonable level */
    }

    return 0;
}
Exemple #7
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);
}
Exemple #8
0
int conn_wait(Connection *conn, double seconds)
{
    int events;
    int ret;
    int fd;

    lock_out(conn);

    /* Try to write any data that might still be waiting to be sent */
    ret = unlocked_write(conn);
    if (ret < 0) {
        unlock_out(conn);
        return -1;
    }
    if (ret > 0) {
        /* We did something useful.  No need to poll or wait now. */
        unlock_out(conn);
        return 0;
    }

    fd = conn->fd;

    /* Normally, we block until there is more data available.  But
     * if any data still needs to be sent, we block until we can
     * send it (or there is more data available).  We always block
     * for reading, unless we know there is no more data coming.
     * (Because in that case, poll will keep reporting POLLIN to
     * signal the end of the file).  If the caller explicitly wants
     * to wait even though there is no data to write and we're at
     * end of file, then poll for new data anyway because the caller
     * apparently doesn't trust eof. */
    events = 0;
    if (unlocked_outbuf_len(conn) > 0)
        events |= POLLOUT;
    /* Don't keep the connection locked while we wait */
    unlock_out(conn);

    /* We need the in lock to query read_eof */
    lock_in(conn);
    if ((conn->read_eof == 0 && conn->io_error == 0) || events == 0)
        events |= POLLIN;
    unlock_in(conn);

    ret = gwthread_pollfd(fd, events, seconds);
    if (ret < 0) {
        if (errno == EINTR)
            return 0;
        error(0, "conn_wait: poll failed on fd %d:", fd);
        return -1;
    }

    if (ret == 0)
        return 1;

    if (ret & POLLNVAL) {
        error(0, "conn_wait: fd %d not open.", fd);
        return -1;
    }

    if (ret & (POLLERR | POLLHUP)) {
        /* Call unlocked_read to report the specific error,
         * and handle the results of the error.  We can't be
         * certain that the error still exists, because we
         * released the lock for a while. */
        lock_in(conn);
        unlocked_read(conn);
        unlock_in(conn);
        return -1;
    }

    /* If POLLOUT is on, then we must have wanted
     * to write something. */
    if (ret & POLLOUT) {
        lock_out(conn);
        unlocked_write(conn);
        unlock_out(conn);
    }

    /* Since we normally select for reading, we must
     * try to read here.  Otherwise, if the caller loops
     * around conn_wait without making conn_read* calls
     * in between, we will keep polling this same data. */
    if (ret & POLLIN) {
        lock_in(conn);
        unlocked_read(conn);
        unlock_in(conn);
    }

    return 0;
}
Exemple #9
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();
}