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.
25 #include <sys/types.h>
26 #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))
153 //printf("[%s] [%s]\n", host, portstring);
157 sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
158 if (sock == -1) return 0;
166 int oldflags = fcntl (sock, F_GETFL, 0);
167 oldflags |= O_NONBLOCK;
168 fcntl(sock, F_SETFL, oldflags);
170 unsigned long flag=1;
171 ioctlsocket(sock,FIONBIO,&flag);
175 // setReceiveWindow(2048);
177 // ok, how to open a connection in non blocking mode (and therefore have a self set timeout!!)
180 int success = connect(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
182 int success = connect(sock, res->ai_addr, res->ai_addrlen);
187 if (success == 0) // if by some miracle the connection succeeded in no time flat, just return!
193 // first check errno for EINPROGRESS, otherwise it's a fail
194 // this doesn't work?
196 if (errno != EINPROGRESS)
198 int wsalasterr = WSAGetLastError();
199 if ((wsalasterr != WSAEWOULDBLOCK) && (wsalasterr != WSAEINPROGRESS))
207 // now do a timeout wait on writability on the socket
210 struct timeval timeout;
211 FD_ZERO(&connectSet);
212 FD_SET(sock, &connectSet);
215 success = select(sock + 1, NULL, &connectSet, NULL, &timeout);
223 // so the socket became available for writing. Contrary to expectation, this doesn't actually
224 // mean it connected...
227 socklen_t soErrorSize = sizeof(soError);
228 int gso = getsockopt(sock, SOL_SOCKET, SO_ERROR,(char*) &soError, &soErrorSize);
230 if ((gso == 0) && (soError == 0))
243 The full documentation:
246 The socket is non-blocking and the connection canĀ
247 not be completed immediately. It is possible to
248 select(2) or poll(2) for completion by selecting
249 the socket for writing. After select indicates
250 writability, use getsockopt(2) to read the SO_ERROR
251 option at level SOL_SOCKET to determine whether
252 connect completed successfully (SO_ERROR is zero)
253 or unsuccessfully (SO_ERROR is one of the usual
254 error codes listed here, explaining the reason for
259 void TCP::setReceiveWindow(size_t rxBufferSize)
261 // Set receive window
262 int r = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&rxBufferSize, sizeof(size_t));
263 Log::getInstance()->log("TCP", Log::DEBUG, "Set receive window to %i, success(=0): %i", rxBufferSize, r);
266 void TCP::assignSocket(int tsocket)
271 int TCP::isConnected()
276 int TCP::sendData(void* bufR, size_t count)
278 size_t bytes_sent = 0;
281 unsigned char* buf = (unsigned char*)bufR;
285 while (bytes_sent < count)
290 this_write = write(sock, buf, count - bytes_sent);
291 // Log::getInstance()->log("TCP", Log::DEBUG, "TCP has written %i bytes", this_write);
292 } while ( (this_write < 0) && (errno == EINTR) );
294 this_write = send(sock,(char*) buf, count- bytes_sent,0);
295 } while ( (this_write == SOCKET_ERROR) && (WSAGetLastError() == WSAEINTR) );
299 MUTEX_UNLOCK(&mutex);
302 bytes_sent += this_write;
306 MUTEX_UNLOCK(&mutex);
311 int TCP::readData(UCHAR* buffer, int totalBytes)
319 struct timeval timeout;
320 struct timeval* passToSelect;
322 if (timeoutEnabled) passToSelect = &timeout;
323 else passToSelect = NULL;
328 FD_SET(sock, &readSet);
331 // Log::getInstance()->log("TCP", Log::DEBUG, "Going to select");
332 success = select(sock + 1, &readSet, NULL, NULL, passToSelect);
333 // Log::getInstance()->log("TCP", Log::DEBUG, "Back from select with success = %i", success);
336 return 0; // error, or timeout
339 thisRead = read(sock, &buffer[bytesRead], totalBytes - bytesRead);
341 thisRead = recv(sock, (char*)&buffer[bytesRead], totalBytes - bytesRead, 0);
343 //Log::getInstance()->log("TCP", Log::DEBUG, "Read %i", thisRead);
346 // if read returns 0 then connection is closed
347 // in non-blocking mode if read is called with no data available, it returns -1
348 // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
349 Log::getInstance()->log("TCP", Log::ERR, "Detected connection closed");
354 bytesRead += thisRead;
355 if (bytesRead == totalBytes)
361 if (++readTries == 1000)
363 Log::getInstance()->log("TCP", Log::ERR, "Too many reads");
370 void TCP::dump(unsigned char* data, ULONG size)
372 printf("Size = %lu\n", size);
379 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",
380 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
381 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15],
382 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]),
383 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]));
391 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",
392 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
393 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14],
394 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]),
395 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]));
399 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",
400 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
401 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13],
402 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]),
403 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]));
407 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",
408 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
409 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12],
410 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]),
411 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]));
415 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",
416 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
417 data[c+8], data[c+9], data[c+10], data[c+11],
418 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]),
419 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]));
423 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c\n",
424 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
425 data[c+8], data[c+9], data[c+10],
426 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]),
427 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]));
431 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c\n",
432 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
433 data[c+8], data[c+9],
434 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]),
435 dcc(data[c+8]), dcc(data[c+9]));
439 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c\n",
440 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
442 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]),
447 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c\n",
448 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
449 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 %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],
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]));
459 printf(" %02X %02X %02X %02X %02X %02X %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],
461 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]));
465 printf(" %02X %02X %02X %02X %02X %c%c%c%c%c\n",
466 data[c], data[c+1], data[c+2], data[c+3], data[c+4],
467 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]));
471 printf(" %02X %02X %02X %02X %c%c%c%c\n",
472 data[c], data[c+1], data[c+2], data[c+3],
473 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]));
477 printf(" %02X %02X %02X %c%c%c\n",
478 data[c], data[c+1], data[c+2],
479 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]));
483 printf(" %02X %02X %c%c\n",
485 dcc(data[c]), dcc(data[c+1]));
499 UCHAR TCP::dcc(UCHAR c)
501 if (isspace(c)) return ' ';
502 if (isprint(c)) return c;