00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include <stdlib.h>
00040 #include <sys/poll.h>
00041
00042 #include "TCPClient.h"
00043 #include "NetUtils.h"
00044 #include "debug/DebugUtils.h"
00045 #include "debug/Log.h"
00046
00047 namespace oasys {
00048
00049 TCPClient::TCPClient(const char* logbase, bool init_socket_immediately)
00050 : IPClient(SOCK_STREAM, logbase)
00051 {
00052 if (init_socket_immediately) {
00053 init_socket();
00054 ASSERT(fd_ != -1);
00055 }
00056 }
00057
00058 TCPClient::TCPClient(int fd, in_addr_t remote_addr, u_int16_t remote_port,
00059 const char* logbase)
00060 : IPClient(SOCK_STREAM, fd, remote_addr, remote_port, logbase)
00061 {
00062 }
00063
00064 int
00065 TCPClient::timeout_connect(in_addr_t remote_addr, u_int16_t remote_port,
00066 int timeout_ms, int* errp)
00067 {
00068 int ret, err;
00069 socklen_t len = sizeof(err);
00070
00071 if (fd_ == -1) init_socket();
00072
00073 if (IO::set_nonblocking(fd_, true, logpath_) < 0) {
00074 log_err("error setting fd %d to nonblocking: %s",
00075 fd_, strerror(errno));
00076 if (errp) *errp = errno;
00077 return IOERROR;
00078 }
00079
00080 ret = IPSocket::connect(remote_addr, remote_port);
00081
00082 if (ret == 0)
00083 {
00084 log_debug("timeout_connect: succeeded immediately");
00085 if (errp) *errp = 0;
00086 ASSERT(state_ == ESTABLISHED);
00087 }
00088 else if (ret < 0 && errno != EINPROGRESS)
00089 {
00090 log_err("timeout_connect: error from connect: %s",
00091 strerror(errno));
00092 if (errp) *errp = errno;
00093 ret = IOERROR;
00094 }
00095 else
00096 {
00097 ASSERT(errno == EINPROGRESS);
00098 log_debug("EINPROGRESS from connect(), calling poll()");
00099 ret = IO::poll_single(fd_, POLLOUT, NULL, timeout_ms,
00100 get_notifier(), logpath_);
00101
00102 if (ret == IOTIMEOUT)
00103 {
00104 log_debug("timeout_connect: poll timeout");
00105 }
00106 else if (ret < 0)
00107 {
00108 log_err("error in poll(): %s", strerror(errno));
00109 if (errp) *errp = errno;
00110 ret = IOERROR;
00111 }
00112 else
00113 {
00114 ASSERT(ret == 1);
00115
00116 ret = getsockopt(fd_, SOL_SOCKET, SO_ERROR, &err, &len);
00117 ASSERT(ret == 0);
00118 if (err == 0) {
00119 log_debug("return from poll, connect succeeded");
00120 ret = 0;
00121 set_state(ESTABLISHED);
00122 } else {
00123 log_debug("return from poll, connect failed");
00124 ret = IOERROR;
00125 }
00126 }
00127 }
00128
00129
00130 if (IO::set_nonblocking(fd_, false, logpath_) < 0) {
00131 log_err("error setting fd %d back to blocking: %s",
00132 fd_, strerror(errno));
00133 if (errp) *errp = errno;
00134 return IOERROR;
00135 }
00136
00137 monitor(IO::CONNECT, 0);
00138
00139 return ret;
00140 }
00141
00142 }