TCPServer.cc

Go to the documentation of this file.
00001 /*
00002  * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By
00003  * downloading, copying, installing or using the software you agree to
00004  * this license. If you do not agree to this license, do not download,
00005  * install, copy or use the software.
00006  * 
00007  * Intel Open Source License 
00008  * 
00009  * Copyright (c) 2004 Intel Corporation. All rights reserved. 
00010  * 
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions are
00013  * met:
00014  * 
00015  *   Redistributions of source code must retain the above copyright
00016  *   notice, this list of conditions and the following disclaimer.
00017  * 
00018  *   Redistributions in binary form must reproduce the above copyright
00019  *   notice, this list of conditions and the following disclaimer in the
00020  *   documentation and/or other materials provided with the distribution.
00021  * 
00022  *   Neither the name of the Intel Corporation nor the names of its
00023  *   contributors may be used to endorse or promote products derived from
00024  *   this software without specific prior written permission.
00025  *  
00026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00027  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00028  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00029  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR
00030  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00031  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00032  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00033  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00034  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00035  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00036  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037  */
00038 
00039 #include "NetUtils.h"
00040 #include "TCPServer.h"
00041 #include "debug/DebugUtils.h"
00042 #include "debug/Log.h"
00043 
00044 #include <errno.h>
00045 #include <sys/poll.h>
00046 #include <sys/types.h>
00047 #include <sys/socket.h>
00048 #include <netinet/in.h>
00049 
00050 namespace oasys {
00051 
00052 TCPServer::TCPServer(const char* logbase)
00053     : IPSocket(SOCK_STREAM, logbase)
00054 {
00055     params_.reuseaddr_ = 1;
00056 }
00057 
00058 int
00059 TCPServer::listen()
00060 {
00061     logf(LOG_DEBUG, "listening");
00062     ASSERT(fd_ != -1);
00063 
00064     if (::listen(fd_, SOMAXCONN) == -1) {
00065         logf(LOG_ERR, "error in listen(): %s",strerror(errno));
00066         return -1;
00067     }
00068     
00069     set_state(LISTENING);
00070     return 0;
00071 }
00072     
00073 int
00074 TCPServer::accept(int *fd, in_addr_t *addr, u_int16_t *port)
00075 {
00076     ASSERTF(state_ == LISTENING,
00077             "accept() expected state LISTENING, not %s", statetoa(state_));
00078     
00079     struct sockaddr_in sa;
00080     socklen_t sl = sizeof(sa);
00081     memset(&sa, 0, sizeof(sa));
00082     int ret = ::accept(fd_, (sockaddr*)&sa, &sl);
00083     if (ret == -1) {
00084         if (errno != EINTR)
00085             logf(LOG_ERR, "error in accept(): %s", strerror(errno));
00086         return ret;
00087     }
00088     
00089     *fd = ret;
00090     *addr = sa.sin_addr.s_addr;
00091     *port = ntohs(sa.sin_port);
00092 
00093     monitor(IO::ACCEPT, 0); // XXX/bowei
00094 
00095     return 0;
00096 }
00097 
00098 int
00099 TCPServer::timeout_accept(int *fd, in_addr_t *addr, u_int16_t *port,
00100                           int timeout_ms)
00101 {
00102     int ret = poll_sockfd(POLLIN, NULL, timeout_ms);
00103 
00104     if (ret != 1) return ret;
00105     ASSERT(ret == 1);
00106 
00107     ret = accept(fd, addr, port);
00108 
00109     if (ret < 0) {
00110         return IOERROR;
00111     }
00112 
00113     monitor(IO::ACCEPT, 0); // XXX/bowei
00114 
00115     return 0; 
00116 }
00117 
00118 void
00119 TCPServerThread::run()
00120 {
00121     int fd;
00122     in_addr_t addr;
00123     u_int16_t port;
00124 
00125     while (1) {
00126         // check if someone has told us to quit by setting the
00127         // should_stop flag. if so, we're all done.
00128         if (should_stop())
00129             break;
00130         
00131         // check the accept_timeout parameter to see if we should
00132         // block or poll when calling accept
00133         int ret;
00134         if (accept_timeout_ == -1) {
00135             ret = accept(&fd, &addr, &port);
00136         } else {
00137             ret = timeout_accept(&fd, &addr, &port, accept_timeout_);
00138             if (ret == IOTIMEOUT)
00139                 continue;
00140         }
00141 
00142         if (ret != 0) {
00143             if (errno == EINTR)
00144                 continue;
00145             
00146             logf(LOG_ERR, "error %d in accept(): %d %s",
00147                  ret, errno, strerror(errno));
00148             close();
00149             break;
00150         }
00151 
00152         logf(LOG_DEBUG, "accepted connection fd %d from %s:%d",
00153              fd, intoa(addr), port);
00154 
00155         accepted(fd, addr, port);
00156     }
00157 }
00158 
00159 int
00160 TCPServerThread::bind_listen_start(in_addr_t local_addr,
00161                                    u_int16_t local_port)
00162 {
00163     if (bind(local_addr, local_port) != 0)
00164         return -1;
00165     
00166     if (listen() != 0)
00167         return -1;
00168     
00169     start();
00170     
00171     return 0;
00172 }
00173 
00174 } // namespace oasys

Generated on Fri Dec 22 14:48:01 2006 for DTN Reference Implementation by  doxygen 1.5.1