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"); } } }
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__); }
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; }
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; }
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"); } }
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; }
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); }
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; }
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(); }