00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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);
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
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
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);
00117
00118 return ret;
00119 }
00120
00121 }