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)
118 #ifdef VOMP_PLATTFORM_RASPBERRY
126 sock = socket(PF_INET, SOCK_STREAM, 0);
127 if (sock == -1) return 0;
128 struct sockaddr_in dest_addr;
129 dest_addr.sin_family = AF_INET;
130 dest_addr.sin_port = htons(port);
133 if (!inet_aton(host, &dest_addr.sin_addr))
135 dest_addr.sin_addr.s_addr = inet_addr(host);
136 if (dest_addr.sin_addr.s_addr == INADDR_NONE)
143 memset(&(dest_addr.sin_zero), '\0', 8);
148 snprintf(portstring, 10, "%u", port);
150 struct addrinfo hints;
151 struct addrinfo* res;
152 memset(&hints, 0, sizeof(hints));
153 hints.ai_family = AF_UNSPEC;
154 hints.ai_socktype = SOCK_STREAM;
155 if (getaddrinfo(host, portstring, &hints, &res))
157 //printf("[%s] [%s]\n", host, portstring);
161 sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
162 if (sock == -1) return 0;
170 int oldflags = fcntl (sock, F_GETFL, 0);
171 oldflags |= O_NONBLOCK;
172 fcntl(sock, F_SETFL, oldflags);
174 unsigned long flag=1;
175 ioctlsocket(sock,FIONBIO,&flag);
179 // setReceiveWindow(2048);
181 // ok, how to open a connection in non blocking mode (and therefore have a self set timeout!!)
184 int success = connect(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
186 int success = connect(sock, res->ai_addr, res->ai_addrlen);
191 if (success == 0) // if by some miracle the connection succeeded in no time flat, just return!
197 // first check errno for EINPROGRESS, otherwise it's a fail
198 // this doesn't work?
200 if (errno != EINPROGRESS)
202 int wsalasterr = WSAGetLastError();
203 if ((wsalasterr != WSAEWOULDBLOCK) && (wsalasterr != WSAEINPROGRESS))
211 // now do a timeout wait on writability on the socket
214 struct timeval timeout;
215 FD_ZERO(&connectSet);
216 FD_SET(sock, &connectSet);
219 success = select(sock + 1, NULL, &connectSet, NULL, &timeout);
227 // so the socket became available for writing. Contrary to expectation, this doesn't actually
228 // mean it connected...
231 socklen_t soErrorSize = sizeof(soError);
232 int gso = getsockopt(sock, SOL_SOCKET, SO_ERROR,(char*) &soError, &soErrorSize);
234 if ((gso == 0) && (soError == 0))
247 The full documentation:
250 The socket is non-blocking and the connection canĀ
251 not be completed immediately. It is possible to
252 select(2) or poll(2) for completion by selecting
253 the socket for writing. After select indicates
254 writability, use getsockopt(2) to read the SO_ERROR
255 option at level SOL_SOCKET to determine whether
256 connect completed successfully (SO_ERROR is zero)
257 or unsuccessfully (SO_ERROR is one of the usual
258 error codes listed here, explaining the reason for
263 void TCP::setReceiveWindow(size_t rxBufferSize)
265 // Set receive window
266 int r = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&rxBufferSize, sizeof(size_t));
267 Log::getInstance()->log("TCP", Log::DEBUG, "Set receive window to %i, success(=0): %i", rxBufferSize, r);
270 void TCP::assignSocket(int tsocket)
275 int TCP::isConnected()
280 int TCP::sendData(void* bufR, size_t count)
282 size_t bytes_sent = 0;
285 unsigned char* buf = (unsigned char*)bufR;
289 while (bytes_sent < count)
294 this_write = write(sock, buf, count - bytes_sent);
295 // Log::getInstance()->log("TCP", Log::DEBUG, "TCP has written %i bytes", this_write);
296 } while ( (this_write < 0) && (errno == EINTR) );
298 this_write = send(sock,(char*) buf, count- bytes_sent,0);
299 } while ( (this_write == SOCKET_ERROR) && (WSAGetLastError() == WSAEINTR) );
303 MUTEX_UNLOCK(&mutex);
306 bytes_sent += this_write;
310 MUTEX_UNLOCK(&mutex);
315 int TCP::readData(UCHAR* buffer, int totalBytes)
323 struct timeval timeout;
324 struct timeval* passToSelect;
326 if (timeoutEnabled) passToSelect = &timeout;
327 else passToSelect = NULL;
332 FD_SET(sock, &readSet);
335 // Log::getInstance()->log("TCP", Log::DEBUG, "Going to select");
336 success = select(sock + 1, &readSet, NULL, NULL, passToSelect);
337 // Log::getInstance()->log("TCP", Log::DEBUG, "Back from select with success = %i", success);
340 return 0; // error, or timeout
343 thisRead = read(sock, &buffer[bytesRead], totalBytes - bytesRead);
345 thisRead = recv(sock, (char*)&buffer[bytesRead], totalBytes - bytesRead, 0);
347 //Log::getInstance()->log("TCP", Log::DEBUG, "Read %i", thisRead);
350 // if read returns 0 then connection is closed
351 // in non-blocking mode if read is called with no data available, it returns -1
352 // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
353 Log::getInstance()->log("TCP", Log::ERR, "Detected connection closed");
358 bytesRead += thisRead;
359 if (bytesRead == totalBytes)
365 if (++readTries == 1000)
367 Log::getInstance()->log("TCP", Log::ERR, "Too many reads");
374 void TCP::dump(unsigned char* data, ULONG size)
376 printf("Size = %lu\n", size);
383 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",
384 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
385 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15],
386 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]),
387 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]));
395 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",
396 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
397 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14],
398 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]),
399 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]));
403 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",
404 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
405 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13],
406 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]),
407 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]));
411 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",
412 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
413 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12],
414 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]),
415 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]));
419 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",
420 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
421 data[c+8], data[c+9], data[c+10], data[c+11],
422 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]),
423 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]));
427 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c\n",
428 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
429 data[c+8], data[c+9], data[c+10],
430 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]),
431 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]));
435 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c\n",
436 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
437 data[c+8], data[c+9],
438 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]),
439 dcc(data[c+8]), dcc(data[c+9]));
443 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c\n",
444 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
446 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]),
451 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c\n",
452 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
453 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]));
457 printf(" %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c\n",
458 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6],
459 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]));
463 printf(" %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c\n",
464 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5],
465 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]));
469 printf(" %02X %02X %02X %02X %02X %c%c%c%c%c\n",
470 data[c], data[c+1], data[c+2], data[c+3], data[c+4],
471 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]));
475 printf(" %02X %02X %02X %02X %c%c%c%c\n",
476 data[c], data[c+1], data[c+2], data[c+3],
477 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]));
481 printf(" %02X %02X %02X %c%c%c\n",
482 data[c], data[c+1], data[c+2],
483 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]));
487 printf(" %02X %02X %c%c\n",
489 dcc(data[c]), dcc(data[c+1]));
503 UCHAR TCP::dcc(UCHAR c)
505 if (isspace(c)) return ' ';
506 if (isprint(c)) return c;