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.
26 #include <sys/types.h>
27 #include <sys/socket.h>
36 #define MUTEX_LOCK(mutex) pthread_mutex_lock(mutex)
37 #define MUTEX_UNLOCK(mutex) pthread_mutex_unlock(mutex)
39 #define MUTEX_LOCK(mutex) WaitForSingleObject(*(mutex), INFINITE )
40 #define MUTEX_UNLOCK(mutex) ReleaseMutex(*(mutex))
50 pthread_mutex_init(&mutex, NULL);
52 mutex=CreateMutex(NULL,FALSE,NULL);
61 Log::getInstance()->log("TCP", Log::DEBUG, "Have closed");
69 void TCP::disableTimeout()
74 void TCP::getMAC(char* dest)
78 strcpy(ifr.ifr_name, "eth0");
79 ioctl(sock, SIOCGIFHWADDR, &ifr);
80 memcpy(dest, ifr.ifr_hwaddr.sa_data, 6);
82 //TODO: Get MAC Address for windows
83 PIP_ADAPTER_INFO daptinfo=NULL;
85 GetAdaptersInfo(daptinfo,&size);
86 daptinfo=(PIP_ADAPTER_INFO)new char[size+1];
87 memcpy(dest,"ABCDEF", 6);//Dummy Address
88 sockaddr_in sock_address;
89 int sockname_len=sizeof(sock_address);
90 getsockname(sock,(sockaddr*)&sock_address,&sockname_len);
91 ULONG sockip=sock_address.sin_addr.s_addr;
92 if (GetAdaptersInfo(daptinfo,&size)==ERROR_SUCCESS)
94 PIP_ADAPTER_INFO daptinfo_it=daptinfo;
95 while (daptinfo_it!=NULL)
97 ULONG ipaddress=inet_addr(daptinfo_it->IpAddressList.IpAddress.String);
98 if (ipaddress==sockip)
100 memcpy(dest,daptinfo_it->Address, 6);
103 daptinfo_it=daptinfo_it->Next;
104 if (daptinfo_it==daptinfo) break;
116 int TCP::connectTo(char* host, unsigned short port)
123 sock = socket(PF_INET, SOCK_STREAM, 0);
124 if (sock == -1) return 0;
125 struct sockaddr_in dest_addr;
126 dest_addr.sin_family = AF_INET;
127 dest_addr.sin_port = htons(port);
130 if (!inet_aton(host, &dest_addr.sin_addr))
132 dest_addr.sin_addr.s_addr = inet_addr(host);
133 if (dest_addr.sin_addr.s_addr == INADDR_NONE)
140 memset(&(dest_addr.sin_zero), '\0', 8);
145 snprintf(portstring, 10, "%u", port);
147 struct addrinfo hints;
148 struct addrinfo* res;
149 memset(&hints, 0, sizeof(hints));
150 hints.ai_family = AF_UNSPEC;
151 hints.ai_socktype = SOCK_STREAM;
152 if (getaddrinfo(host, portstring, &hints, &res))
154 //printf("[%s] [%s]\n", host, portstring);
158 sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
159 if (sock == -1) return 0;
167 int oldflags = fcntl (sock, F_GETFL, 0);
168 oldflags |= O_NONBLOCK;
169 fcntl(sock, F_SETFL, oldflags);
171 unsigned long flag=1;
172 ioctlsocket(sock,FIONBIO,&flag);
176 // setReceiveWindow(2048);
178 // ok, how to open a connection in non blocking mode (and therefore have a self set timeout!!)
181 int success = connect(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
183 int success = connect(sock, res->ai_addr, res->ai_addrlen);
188 if (success == 0) // if by some miracle the connection succeeded in no time flat, just return!
194 // first check errno for EINPROGRESS, otherwise it's a fail
195 // this doesn't work?
197 if (errno != EINPROGRESS)
199 int wsalasterr = WSAGetLastError();
200 if ((wsalasterr != WSAEWOULDBLOCK) && (wsalasterr != WSAEINPROGRESS))
208 // now do a timeout wait on writability on the socket
211 struct timeval timeout;
212 FD_ZERO(&connectSet);
213 FD_SET(sock, &connectSet);
216 success = select(sock + 1, NULL, &connectSet, NULL, &timeout);
224 // so the socket became available for writing. Contrary to expectation, this doesn't actually
225 // mean it connected...
228 socklen_t soErrorSize = sizeof(soError);
229 int gso = getsockopt(sock, SOL_SOCKET, SO_ERROR,(char*) &soError, &soErrorSize);
231 if ((gso == 0) && (soError == 0))
244 The full documentation:
247 The socket is non-blocking and the connection canĀ
248 not be completed immediately. It is possible to
249 select(2) or poll(2) for completion by selecting
250 the socket for writing. After select indicates
251 writability, use getsockopt(2) to read the SO_ERROR
252 option at level SOL_SOCKET to determine whether
253 connect completed successfully (SO_ERROR is zero)
254 or unsuccessfully (SO_ERROR is one of the usual
255 error codes listed here, explaining the reason for
260 void TCP::setReceiveWindow(size_t rxBufferSize)
262 // Set receive window
263 int r = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&rxBufferSize, sizeof(size_t));
264 Log::getInstance()->log("TCP", Log::DEBUG, "Set receive window to %i, success(=0): %i", rxBufferSize, r);
267 void TCP::assignSocket(int tsocket)
272 int TCP::isConnected()
277 int TCP::sendData(void* bufR, size_t count)
279 size_t bytes_sent = 0;
282 unsigned char* buf = (unsigned char*)bufR;
286 while (bytes_sent < count)
291 this_write = write(sock, buf, count - bytes_sent);
292 // Log::getInstance()->log("TCP", Log::DEBUG, "TCP has written %i bytes", this_write);
293 } while ( (this_write < 0) && (errno == EINTR) );
295 this_write = send(sock,(char*) buf, count- bytes_sent,0);
296 } while ( (this_write == SOCKET_ERROR) && (WSAGetLastError() == WSAEINTR) );
300 MUTEX_UNLOCK(&mutex);
303 bytes_sent += this_write;
307 MUTEX_UNLOCK(&mutex);
312 int TCP::readData(UCHAR* buffer, int totalBytes)
320 struct timeval timeout;
321 struct timeval* passToSelect;
323 if (timeoutEnabled) passToSelect = &timeout;
324 else passToSelect = NULL;
329 FD_SET(sock, &readSet);
332 // Log::getInstance()->log("TCP", Log::DEBUG, "Going to select");
333 success = select(sock + 1, &readSet, NULL, NULL, passToSelect);
334 // Log::getInstance()->log("TCP", Log::DEBUG, "Back from select with success = %i", success);
337 return 0; // error, or timeout
340 thisRead = read(sock, &buffer[bytesRead], totalBytes - bytesRead);
342 thisRead = recv(sock, (char*)&buffer[bytesRead], totalBytes - bytesRead, 0);
344 //Log::getInstance()->log("TCP", Log::DEBUG, "Read %i", thisRead);
347 // if read returns 0 then connection is closed
348 // in non-blocking mode if read is called with no data available, it returns -1
349 // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
350 Log::getInstance()->log("TCP", Log::ERR, "Detected connection closed");
355 bytesRead += thisRead;
356 if (bytesRead == totalBytes)
362 if (++readTries == 1000)
364 Log::getInstance()->log("TCP", Log::ERR, "Too many reads");
371 void TCP::dump(unsigned char* data, ULONG size)
373 printf("Size = %lu\n", size);
380 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",
381 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
382 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15],
383 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]),
384 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]));
392 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",
393 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
394 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14],
395 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]),
396 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]));
400 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",
401 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
402 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13],
403 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]),
404 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]));
408 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",
409 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
410 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12],
411 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]),
412 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]));
416 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",
417 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
418 data[c+8], data[c+9], data[c+10], data[c+11],
419 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]),
420 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]));
424 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c\n",
425 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
426 data[c+8], data[c+9], data[c+10],
427 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]),
428 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]));
432 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c\n",
433 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
434 data[c+8], data[c+9],
435 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]),
436 dcc(data[c+8]), dcc(data[c+9]));
440 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c\n",
441 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
443 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]),
448 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c\n",
449 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
450 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]));
454 printf(" %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c\n",
455 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6],
456 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]));
460 printf(" %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c\n",
461 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5],
462 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]));
466 printf(" %02X %02X %02X %02X %02X %c%c%c%c%c\n",
467 data[c], data[c+1], data[c+2], data[c+3], data[c+4],
468 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]));
472 printf(" %02X %02X %02X %02X %c%c%c%c\n",
473 data[c], data[c+1], data[c+2], data[c+3],
474 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]));
478 printf(" %02X %02X %02X %c%c%c\n",
479 data[c], data[c+1], data[c+2],
480 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]));
484 printf(" %02X %02X %c%c\n",
486 dcc(data[c]), dcc(data[c+1]));
500 UCHAR TCP::dcc(UCHAR c)
502 if (isspace(c)) return ' ';
503 if (isprint(c)) return c;