00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "NetUtils.h"
00019 #include "TCPServer.h"
00020 #include "debug/DebugUtils.h"
00021 #include "debug/Log.h"
00022
00023 #include <errno.h>
00024 #include <sys/poll.h>
00025 #include <sys/types.h>
00026 #include <sys/socket.h>
00027 #include <netinet/in.h>
00028
00029 namespace oasys {
00030
00031 TCPServer::TCPServer(const char* logbase)
00032 : IPSocket(SOCK_STREAM, logbase)
00033 {
00034 params_.reuseaddr_ = 1;
00035 }
00036
00037 int
00038 TCPServer::listen()
00039 {
00040 logf(LOG_DEBUG, "listening");
00041 ASSERT(fd_ != -1);
00042
00043 if (::listen(fd_, SOMAXCONN) == -1) {
00044 logf(LOG_ERR, "error in listen(): %s",strerror(errno));
00045 return -1;
00046 }
00047
00048 set_state(LISTENING);
00049 return 0;
00050 }
00051
00052 int
00053 TCPServer::accept(int *fd, in_addr_t *addr, u_int16_t *port)
00054 {
00055 ASSERTF(state_ == LISTENING,
00056 "accept() expected state LISTENING, not %s", statetoa(state_));
00057
00058 struct sockaddr_in sa;
00059 socklen_t sl = sizeof(sa);
00060 memset(&sa, 0, sizeof(sa));
00061 int ret = ::accept(fd_, (sockaddr*)&sa, &sl);
00062 if (ret == -1) {
00063 if (errno != EINTR)
00064 logf(LOG_ERR, "error in accept(): %s", strerror(errno));
00065 return ret;
00066 }
00067
00068 *fd = ret;
00069 *addr = sa.sin_addr.s_addr;
00070 *port = ntohs(sa.sin_port);
00071
00072 monitor(IO::ACCEPT, 0);
00073
00074 return 0;
00075 }
00076
00077 int
00078 TCPServer::timeout_accept(int *fd, in_addr_t *addr, u_int16_t *port,
00079 int timeout_ms)
00080 {
00081 int ret = poll_sockfd(POLLIN, NULL, timeout_ms);
00082
00083 if (ret != 1) return ret;
00084 ASSERT(ret == 1);
00085
00086 ret = accept(fd, addr, port);
00087
00088 if (ret < 0) {
00089 return IOERROR;
00090 }
00091
00092 monitor(IO::ACCEPT, 0);
00093
00094 return 0;
00095 }
00096
00097 void
00098 TCPServerThread::run()
00099 {
00100 int fd;
00101 in_addr_t addr;
00102 u_int16_t port;
00103
00104 while (1) {
00105
00106
00107 if (should_stop())
00108 break;
00109
00110
00111
00112 int ret;
00113 if (accept_timeout_ == -1) {
00114 ret = accept(&fd, &addr, &port);
00115 } else {
00116 ret = timeout_accept(&fd, &addr, &port, accept_timeout_);
00117 if (ret == IOTIMEOUT)
00118 continue;
00119 }
00120
00121 if (ret != 0) {
00122 if (errno == EINTR)
00123 continue;
00124
00125 logf(LOG_ERR, "error %d in accept(): %d %s",
00126 ret, errno, strerror(errno));
00127 close();
00128 break;
00129 }
00130
00131 logf(LOG_DEBUG, "accepted connection fd %d from %s:%d",
00132 fd, intoa(addr), port);
00133
00134 accepted(fd, addr, port);
00135 }
00136 }
00137
00138 int
00139 TCPServerThread::bind_listen_start(in_addr_t local_addr,
00140 u_int16_t local_port)
00141 {
00142 if (bind(local_addr, local_port) != 0)
00143 return -1;
00144
00145 if (listen() != 0)
00146 return -1;
00147
00148 start();
00149
00150 return 0;
00151 }
00152
00153 }