Changeset 238 in flair-src for trunk/lib/FlairCore/src/TcpSocket.cpp
- Timestamp:
- May 15, 2018, 4:41:02 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/lib/FlairCore/src/TcpSocket.cpp
r231 r238 22 22 #include <fcntl.h> 23 23 #include <string.h> 24 #include <system_error> 24 25 25 26 using std::string; … … 30 31 TcpSocket::TcpSocket(const Object *parent, const std::string name, 31 32 bool _blockOnSend, bool _blockOnReceive) 32 : ConnectedSocket(parent, name), isConnected(false) {33 : ConnectedSocket(parent, name), socket(0), isConnected(false), isListening(false), distantPort(0), distantAddress() { 33 34 blockOnSend = _blockOnSend; 34 35 blockOnReceive = _blockOnReceive; … … 37 38 TcpSocket::~TcpSocket() { 38 39 // Info("Debug: destroying TCP socket %s", ObjectName().c_str()); 39 close(socket);40 if (socket) close(socket); 40 41 } 41 42 … … 59 60 } 60 61 61 listen(socket, 1); 62 int ret=listen(socket, 1); 63 if (ret < 0) { 64 char errorMsg[256]; 65 Err("select: %s\n", strerror_r(errno, errorMsg, sizeof(errorMsg))); 66 } else { 67 isListening=true; 68 } 62 69 } 63 70 64 71 TcpSocket *TcpSocket::Accept(Time timeout) { 72 if (!isListening) throw std::logic_error("Can't call Accept on a non listening socket"); 73 65 74 TcpSocket *acceptedSocket = nullptr; 66 75 67 76 struct timeval tv; 68 77 if (timeout != 0) { 69 tv.tv_sec = timeout / 1000 ; // timeout is in ms70 tv.tv_usec = (timeout % 1000 ) *1000;78 tv.tv_sec = timeout / 1000000000; 79 tv.tv_usec = (timeout % 1000000000) / 1000; 71 80 } 72 81 fd_set rset; … … 81 90 if (ret == 0) { 82 91 // timeout reached 83 // Err("timeout reached\n");92 throw std::runtime_error("Timeout"); 84 93 } else { 85 94 // our socket is readable, a new connection can be accepted … … 88 97 sockaddr_in their_addr; 89 98 socklen_t namelen = sizeof(their_addr); 90 if ((acceptedSocket->socket = 91 accept(socket, (sockaddr *)&their_addr, &namelen)) < 0) { 92 char errorMsg[256]; 93 Err("error: %s\n", strerror_r(errno, errorMsg, sizeof(errorMsg))); 99 ret = accept(socket, (sockaddr *)&their_addr, &namelen); 100 if (ret < 0) { 94 101 delete acceptedSocket; 95 acceptedSocket = nullptr; 102 throw std::system_error(std::error_code(ret, std::generic_category())); 103 } else { 104 acceptedSocket->socket = ret; 96 105 } 97 106 } … … 101 110 } 102 111 103 bool TcpSocket::Connect(const unsigned int distantPort,104 const std::string distantAddress, Time timeout) {112 bool TcpSocket::Connect(const unsigned int _distantPort, 113 const std::string _distantAddress, Time timeout) { 105 114 bool success = false; 106 115 bool criticalError=false; //meaning: if true then this socket can't be re-used 116 117 //should we open a new socket, close it, or re-use it? 107 118 if (isConnected) { 108 if (this->distantPort == distantPort &&109 this->distantAddress ==distantAddress) {119 // if already connected to the same host, just return true 120 if (distantPort == _distantPort && distantAddress == _distantAddress) { 110 121 return true; 111 } else { 122 } 123 // if already connected, but to a different host, close the current socket 124 else { 125 isConnected=false; 112 126 close(socket); 113 } 114 } 115 socket = ::socket(AF_INET, SOCK_STREAM, 0); 116 if (socket == -1) 117 return false; 127 socket=0; 128 } 129 } 130 if (!socket) { 131 socket = ::socket(AF_INET, SOCK_STREAM, 0); 132 if (socket == -1) 133 return false; 134 } 118 135 119 136 sockaddr_in serv_addr; … … 123 140 printf("incorrect network address."); 124 141 close(socket); 142 socket=0; 125 143 return false; 126 144 } … … 135 153 Err("socket connect: %s\n", 136 154 strerror_r(errno, errorMsg, sizeof(errorMsg))); 137 success = false;155 criticalError = true; 138 156 } else { 139 157 // now block with a timeout … … 152 170 char errorMsg[256]; 153 171 Err("select: %s\n", strerror_r(errno, errorMsg, sizeof(errorMsg))); 154 success = false;172 criticalError = true; 155 173 } else { 156 if (ret == 0) { 157 // timeout reached 158 // Err("timeout reached\n"); 159 success = false; 160 } else { 161 // something happened on our socket. Check if an error occured 174 if (ret != 0) { //if ret==0 we're on timeout (nothing to do since success is already set to false) 175 // something happened on our socket. Check if an error occurred 162 176 int error; 163 177 socklen_t len = sizeof(error); … … 165 179 //char errorMsg[256]; 166 180 // Err("getsockopt: %s\n",strerror_r(errno,errorMsg,sizeof(errorMsg))); 167 success = false;181 criticalError = true; 168 182 } else if (error != 0) { 169 183 //char errorMsg[256]; 170 184 // Err("socket error: %d(%s)\n",error,strerror_r(error,errorMsg,sizeof(errorMsg))); 171 success = false;185 criticalError = true; 172 186 } else { 173 if (connect(socket, (sockaddr *)&serv_addr, sizeof(serv_addr)) == 174 -1) { 175 success = false; 176 } else { 187 if (connect(socket, (sockaddr *)&serv_addr, sizeof(serv_addr)) != -1) { 177 188 // Info("connected indeed ^^\n"); 178 189 success = true; 190 } else { 191 //connect failed 192 if ((errno != EINPROGRESS) && (errno != EAGAIN)) { 193 criticalError = true; 194 } 179 195 } 180 196 } … … 183 199 } 184 200 } else { 185 success = true; // never reached suprisingly...201 success = true; // should never happen since we go non blocking and connect can't be immediate 186 202 } 187 203 // switch back to blocking mode (default) … … 189 205 190 206 if (!success) { 191 close(socket); 207 if (criticalError) { 208 close(socket); 209 socket=0; 210 } 211 isConnected=false; 192 212 //Info("Debug: Connect to %s:%d failed\n", distantAddress.c_str(), distantPort); 193 213 return false; 194 214 } else { 195 215 isConnected = true; 196 this->distantPort =distantPort;197 this->distantAddress =distantAddress;216 distantPort = _distantPort; 217 distantAddress = _distantAddress; 198 218 //Info("Debug: Connect to %s:%d succeeded\n", distantAddress.c_str(), distantPort); 199 219 return true; … … 208 228 } else { 209 229 struct timeval tv; 210 tv.tv_sec = timeout / 1000 ; // timeout is in ms211 tv.tv_usec = (timeout % 1000 ) *1000;230 tv.tv_sec = timeout / 1000000000; // timeout is in ns 231 tv.tv_usec = (timeout % 1000000000) / 1000; 212 232 213 233 setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, … … 225 245 } else { 226 246 struct timeval tv; 227 tv.tv_sec = timeout / 1000 ; // timeout is in ms228 tv.tv_usec = (timeout % 1000 ) *1000;247 tv.tv_sec = timeout / 1000000000; // timeout is in ns 248 tv.tv_usec = (timeout % 1000000000) / 1000; 229 249 230 250 setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,
Note:
See TracChangeset
for help on using the changeset viewer.