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_PLATFORM_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...
230 int soError; // SO_ERROR optval is int
231 socklen_t soErrorSize = sizeof(soError);
232 int gso = getsockopt(sock, SOL_SOCKET, SO_ERROR, reinterpret_cast<void*>(&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 // According to docs, optval in setsockopt is a pointer to int unless otherwise noted
267 int rxSize = rxBufferSize;
268 int r = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, reinterpret_cast<void*>(&rxSize), sizeof(size_t));
269 Log::getInstance()->log("TCP", Log::DEBUG, "Set receive window to %i, success(=0): %i", rxBufferSize, r);
272 void TCP::assignSocket(int tsocket)
277 int TCP::isConnected()
282 int TCP::sendData(void* bufR, size_t count)
284 size_t bytes_sent = 0;
287 unsigned char* buf = static_cast<unsigned char*>(bufR);
291 while (bytes_sent < count)
296 this_write = write(sock, buf, count - bytes_sent);
297 // Log::getInstance()->log("TCP", Log::DEBUG, "TCP has written %i bytes", this_write);
298 } while ( (this_write < 0) && (errno == EINTR) );
300 this_write = send(sock,(char*) buf, count- bytes_sent,0);
301 } while ( (this_write == SOCKET_ERROR) && (WSAGetLastError() == WSAEINTR) );
305 MUTEX_UNLOCK(&mutex);
308 bytes_sent += this_write;
312 MUTEX_UNLOCK(&mutex);
317 int TCP::readData(UCHAR* buffer, int totalBytes)
325 struct timeval timeout;
326 struct timeval* passToSelect;
328 if (timeoutEnabled) passToSelect = &timeout;
329 else passToSelect = NULL;
334 FD_SET(sock, &readSet);
337 // Log::getInstance()->log("TCP", Log::DEBUG, "Going to select");
338 success = select(sock + 1, &readSet, NULL, NULL, passToSelect);
339 // Log::getInstance()->log("TCP", Log::DEBUG, "Back from select with success = %i", success);
342 return 0; // error, or timeout
345 thisRead = read(sock, &buffer[bytesRead], totalBytes - bytesRead);
347 thisRead = recv(sock, (char*)&buffer[bytesRead], totalBytes - bytesRead, 0);
349 //Log::getInstance()->log("TCP", Log::DEBUG, "Read %i", thisRead);
352 // if read returns 0 then connection is closed
353 // in non-blocking mode if read is called with no data available, it returns -1
354 // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
355 Log::getInstance()->log("TCP", Log::ERR, "Detected connection closed");
360 bytesRead += thisRead;
361 if (bytesRead == totalBytes)
367 if (++readTries == 1000)
369 Log::getInstance()->log("TCP", Log::ERR, "Too many reads");
376 void TCP::dump(unsigned char* data, ULONG size)
378 printf("Size = %lu\n", size);
385 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",
386 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
387 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15],
388 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]),
389 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]));
397 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",
398 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
399 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14],
400 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]),
401 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]));
405 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",
406 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
407 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13],
408 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]),
409 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]));
413 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",
414 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
415 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12],
416 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]),
417 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]));
421 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",
422 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
423 data[c+8], data[c+9], data[c+10], data[c+11],
424 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]),
425 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]));
429 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c\n",
430 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
431 data[c+8], data[c+9], data[c+10],
432 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]),
433 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]));
437 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c\n",
438 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
439 data[c+8], data[c+9],
440 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]),
441 dcc(data[c+8]), dcc(data[c+9]));
445 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c\n",
446 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]),
453 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c\n",
454 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
455 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]));
459 printf(" %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c\n",
460 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6],
461 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]));
465 printf(" %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c\n",
466 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5],
467 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]));
471 printf(" %02X %02X %02X %02X %02X %c%c%c%c%c\n",
472 data[c], data[c+1], data[c+2], data[c+3], data[c+4],
473 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]));
477 printf(" %02X %02X %02X %02X %c%c%c%c\n",
478 data[c], data[c+1], data[c+2], data[c+3],
479 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]));
483 printf(" %02X %02X %02X %c%c%c\n",
484 data[c], data[c+1], data[c+2],
485 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]));
489 printf(" %02X %02X %c%c\n",
491 dcc(data[c]), dcc(data[c+1]));
505 UCHAR TCP::dcc(UCHAR c)
507 if (isspace(c)) return ' ';
508 if (isprint(c)) return c;