2 Copyright 2004-2019 Chris Tallon
3 Copyright 2003-2004 University Of Bradford
5 This file is part of VOMP.
7 VOMP is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 VOMP is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with VOMP; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #include <sys/types.h>
23 #include <sys/socket.h>
35 #define MUTEX_LOCK(mutex) pthread_mutex_lock(mutex)
36 #define MUTEX_UNLOCK(mutex) pthread_mutex_unlock(mutex)
38 #define MUTEX_LOCK(mutex) WaitForSingleObject(*(mutex), INFINITE )
39 #define MUTEX_UNLOCK(mutex) ReleaseMutex(*(mutex))
49 pthread_mutex_init(&mutex, NULL);
51 mutex=CreateMutex(NULL,FALSE,NULL);
60 Log::getInstance()->log("TCP", Log::DEBUG, "Have closed");
68 void TCP::disableTimeout()
73 void TCP::getMAC(char* dest)
77 strcpy(ifr.ifr_name, "eth0");
78 ioctl(sock, SIOCGIFHWADDR, &ifr);
79 memcpy(dest, ifr.ifr_hwaddr.sa_data, 6);
81 //TODO: Get MAC Address for windows
82 PIP_ADAPTER_INFO daptinfo=NULL;
84 GetAdaptersInfo(daptinfo,&size);
85 daptinfo=(PIP_ADAPTER_INFO)new char[size+1];
86 memcpy(dest,"ABCDEF", 6);//Dummy Address
87 sockaddr_in sock_address;
88 int sockname_len=sizeof(sock_address);
89 getsockname(sock,(sockaddr*)&sock_address,&sockname_len);
90 ULONG sockip=sock_address.sin_addr.s_addr;
91 if (GetAdaptersInfo(daptinfo,&size)==ERROR_SUCCESS)
93 PIP_ADAPTER_INFO daptinfo_it=daptinfo;
94 while (daptinfo_it!=NULL)
96 ULONG ipaddress=inet_addr(daptinfo_it->IpAddressList.IpAddress.String);
97 if (ipaddress==sockip)
99 memcpy(dest,daptinfo_it->Address, 6);
102 daptinfo_it=daptinfo_it->Next;
103 if (daptinfo_it==daptinfo) break;
115 int TCP::connectTo(char* host, unsigned short port)
122 sock = socket(PF_INET, SOCK_STREAM, 0);
123 if (sock == -1) return 0;
124 struct sockaddr_in dest_addr;
125 dest_addr.sin_family = AF_INET;
126 dest_addr.sin_port = htons(port);
129 if (!inet_aton(host, &dest_addr.sin_addr))
131 dest_addr.sin_addr.s_addr = inet_addr(host);
132 if (dest_addr.sin_addr.s_addr == INADDR_NONE)
139 memset(&(dest_addr.sin_zero), '\0', 8);
144 snprintf(portstring, 10, "%u", port);
146 struct addrinfo hints;
147 struct addrinfo* res;
148 memset(&hints, 0, sizeof(hints));
149 hints.ai_family = AF_UNSPEC;
150 hints.ai_socktype = SOCK_STREAM;
151 if (getaddrinfo(host, portstring, &hints, &res))
156 sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
157 if (sock == -1) return 0;
165 int oldflags = fcntl (sock, F_GETFL, 0);
166 oldflags |= O_NONBLOCK;
167 fcntl(sock, F_SETFL, oldflags);
169 unsigned long flag=1;
170 ioctlsocket(sock,FIONBIO,&flag);
174 // setReceiveWindow(2048);
176 // ok, how to open a connection in non blocking mode (and therefore have a self set timeout!!)
179 int success = connect(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
181 int success = connect(sock, res->ai_addr, res->ai_addrlen);
186 if (success == 0) // if by some miracle the connection succeeded in no time flat, just return!
192 // first check errno for EINPROGRESS, otherwise it's a fail
193 // this doesn't work?
195 if (errno != EINPROGRESS)
197 int wsalasterr = WSAGetLastError();
198 if ((wsalasterr != WSAEWOULDBLOCK) && (wsalasterr != WSAEINPROGRESS))
206 // now do a timeout wait on writability on the socket
209 struct timeval timeout;
210 FD_ZERO(&connectSet);
211 FD_SET(sock, &connectSet);
214 success = select(sock + 1, NULL, &connectSet, NULL, &timeout);
222 // so the socket became available for writing. Contrary to expectation, this doesn't actually
223 // mean it connected...
226 socklen_t soErrorSize = sizeof(soError);
227 int gso = getsockopt(sock, SOL_SOCKET, SO_ERROR,(char*) &soError, &soErrorSize);
229 if ((gso == 0) && (soError == 0))
242 The full documentation:
245 The socket is non-blocking and the connection canĀ
246 not be completed immediately. It is possible to
247 select(2) or poll(2) for completion by selecting
248 the socket for writing. After select indicates
249 writability, use getsockopt(2) to read the SO_ERROR
250 option at level SOL_SOCKET to determine whether
251 connect completed successfully (SO_ERROR is zero)
252 or unsuccessfully (SO_ERROR is one of the usual
253 error codes listed here, explaining the reason for
258 void TCP::setReceiveWindow(size_t rxBufferSize)
260 // Set receive window
261 int r = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&rxBufferSize, sizeof(size_t));
262 Log::getInstance()->log("TCP", Log::DEBUG, "Set receive window to %i, success(=0): %i", rxBufferSize, r);
265 void TCP::assignSocket(int tsocket)
270 int TCP::isConnected()
275 int TCP::sendData(void* bufR, size_t count)
277 size_t bytes_sent = 0;
280 unsigned char* buf = (unsigned char*)bufR;
284 while (bytes_sent < count)
289 this_write = write(sock, buf, count - bytes_sent);
290 // Log::getInstance()->log("TCP", Log::DEBUG, "TCP has written %i bytes", this_write);
291 } while ( (this_write < 0) && (errno == EINTR) );
293 this_write = send(sock,(char*) buf, count- bytes_sent,0);
294 } while ( (this_write == SOCKET_ERROR) && (WSAGetLastError() == WSAEINTR) );
298 MUTEX_UNLOCK(&mutex);
301 bytes_sent += this_write;
305 MUTEX_UNLOCK(&mutex);
310 int TCP::readData(UCHAR* buffer, int totalBytes)
318 struct timeval timeout;
319 struct timeval* passToSelect;
321 if (timeoutEnabled) passToSelect = &timeout;
322 else passToSelect = NULL;
327 FD_SET(sock, &readSet);
330 // Log::getInstance()->log("TCP", Log::DEBUG, "Going to select");
331 success = select(sock + 1, &readSet, NULL, NULL, passToSelect);
332 // Log::getInstance()->log("TCP", Log::DEBUG, "Back from select with success = %i", success);
335 return 0; // error, or timeout
338 thisRead = read(sock, &buffer[bytesRead], totalBytes - bytesRead);
340 thisRead = recv(sock, (char*)&buffer[bytesRead], totalBytes - bytesRead, 0);
342 //Log::getInstance()->log("TCP", Log::DEBUG, "Read %i", thisRead);
345 // if read returns 0 then connection is closed
346 // in non-blocking mode if read is called with no data available, it returns -1
347 // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
348 Log::getInstance()->log("TCP", Log::ERR, "Detected connection closed");
353 bytesRead += thisRead;
354 if (bytesRead == totalBytes)
360 if (++readTries == 1000)
362 Log::getInstance()->log("TCP", Log::ERR, "Too many reads");
369 void TCP::dump(unsigned char* data, ULONG size)
371 printf("Size = %lu\n", size);
378 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
379 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
380 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15],
381 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
382 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]), dcc(data[c+14]), dcc(data[c+15]));
390 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
391 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
392 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14],
393 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
394 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]), dcc(data[c+14]));
398 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
399 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
400 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13],
401 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
402 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]));
406 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c%c%c\n",
407 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
408 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12],
409 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
410 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]));
414 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c%c\n",
415 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
416 data[c+8], data[c+9], data[c+10], data[c+11],
417 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
418 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]));
422 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c\n",
423 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
424 data[c+8], data[c+9], data[c+10],
425 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
426 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]));
430 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c\n",
431 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
432 data[c+8], data[c+9],
433 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
434 dcc(data[c+8]), dcc(data[c+9]));
438 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c\n",
439 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
441 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
446 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c\n",
447 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
448 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]));
452 printf(" %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c\n",
453 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6],
454 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]));
458 printf(" %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c\n",
459 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5],
460 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]));
464 printf(" %02X %02X %02X %02X %02X %c%c%c%c%c\n",
465 data[c], data[c+1], data[c+2], data[c+3], data[c+4],
466 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]));
470 printf(" %02X %02X %02X %02X %c%c%c%c\n",
471 data[c], data[c+1], data[c+2], data[c+3],
472 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]));
476 printf(" %02X %02X %02X %c%c%c\n",
477 data[c], data[c+1], data[c+2],
478 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]));
482 printf(" %02X %02X %c%c\n",
484 dcc(data[c]), dcc(data[c+1]));
498 UCHAR TCP::dcc(UCHAR c)
500 if (isspace(c)) return ' ';
501 if (isprint(c)) return c;