TCPServer.cc

Go to the documentation of this file.
00001 /*
00002  *    Copyright 2004-2006 Intel Corporation
00003  * 
00004  *    Licensed under the Apache License, Version 2.0 (the "License");
00005  *    you may not use this file except in compliance with the License.
00006  *    You may obtain a copy of the License at
00007  * 
00008  *        http://www.apache.org/licenses/LICENSE-2.0
00009  * 
00010  *    Unless required by applicable law or agreed to in writing, software
00011  *    distributed under the License is distributed on an "AS IS" BASIS,
00012  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *    See the License for the specific language governing permissions and
00014  *    limitations under the License.
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); // XXX/bowei
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); // XXX/bowei
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         // check if someone has told us to quit by setting the
00106         // should_stop flag. if so, we're all done.
00107         if (should_stop())
00108             break;
00109         
00110         // check the accept_timeout parameter to see if we should
00111         // block or poll when calling accept
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 } // namespace oasys

Generated on Sat Sep 8 08:36:18 2007 for DTN Reference Implementation by  doxygen 1.5.3