TCPClient.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 <stdlib.h>
00019 #include <sys/poll.h>
00020 
00021 #include "TCPClient.h"
00022 #include "NetUtils.h"
00023 #include "debug/DebugUtils.h"
00024 #include "debug/Log.h"
00025 
00026 namespace oasys {
00027 
00028 TCPClient::TCPClient(const char* logbase, bool init_socket_immediately)
00029     : IPClient(SOCK_STREAM, logbase)
00030 {
00031     if (init_socket_immediately) {
00032         init_socket();
00033         ASSERT(fd_ != -1);
00034     }
00035 }
00036 
00037 TCPClient::TCPClient(int fd, in_addr_t remote_addr, u_int16_t remote_port,
00038                      const char* logbase)
00039     : IPClient(SOCK_STREAM, fd, remote_addr, remote_port, logbase)
00040 {
00041 }
00042 
00043 int
00044 TCPClient::timeout_connect(in_addr_t remote_addr, u_int16_t remote_port,
00045                            int timeout_ms, int* errp)
00046 {
00047     int ret, err;
00048     socklen_t len = sizeof(err);
00049 
00050     if (fd_ == -1) init_socket();
00051 
00052     if (IO::set_nonblocking(fd_, true, logpath_) < 0) {
00053         log_err("error setting fd %d to nonblocking: %s",
00054                 fd_, strerror(errno));
00055         if (errp) *errp = errno;
00056         return IOERROR;
00057     }
00058     
00059     ret = IPSocket::connect(remote_addr, remote_port);
00060     
00061     if (ret == 0)
00062     {
00063         log_debug("timeout_connect: succeeded immediately");
00064         if (errp) *errp = 0;
00065         ASSERT(state_ == ESTABLISHED); // set by IPSocket
00066     }
00067     else if (ret < 0 && errno != EINPROGRESS)
00068     {
00069         log_err("timeout_connect: error from connect: %s",
00070                 strerror(errno));
00071         if (errp) *errp = errno;
00072         ret = IOERROR;
00073     }
00074     else
00075     {
00076         ASSERT(errno == EINPROGRESS);
00077         log_debug("EINPROGRESS from connect(), calling poll()");
00078         ret = IO::poll_single(fd_, POLLOUT, NULL, timeout_ms, 
00079                               get_notifier(), logpath_);
00080         
00081         if (ret == IOTIMEOUT)
00082         {
00083             log_debug("timeout_connect: poll timeout");
00084         }
00085         else if (ret < 0) 
00086         {
00087             log_err("error in poll(): %s", strerror(errno));
00088             if (errp) *errp = errno;
00089             ret = IOERROR;
00090         }
00091         else
00092         {
00093             ASSERT(ret == 1);
00094             // call getsockopt() to see if connect succeeded
00095             ret = getsockopt(fd_, SOL_SOCKET, SO_ERROR, &err, &len);
00096             ASSERT(ret == 0);
00097             if (err == 0) {
00098                 log_debug("return from poll, connect succeeded");
00099                 ret = 0;
00100                 set_state(ESTABLISHED);
00101             } else {
00102                 log_debug("return from poll, connect failed");
00103                 ret = IOERROR;
00104             }
00105         }
00106     }
00107 
00108     // always make sure to set the fd back to blocking
00109     if (IO::set_nonblocking(fd_, false, logpath_) < 0) {
00110         log_err("error setting fd %d back to blocking: %s",
00111                 fd_, strerror(errno));
00112         if (errp) *errp = errno;
00113         return IOERROR;
00114     }
00115     
00116     monitor(IO::CONNECT, 0); // XXX/bowei
00117 
00118     return ret;
00119 }
00120 
00121 } // namespace oasys

Generated on Thu Jun 7 12:54:29 2007 for DTN Reference Implementation by  doxygen 1.5.1