2 Copyright 2004-2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
41 Log::getInstance()->log("TCP", Log::DEBUG, "Have closed");
45 void TCP::disableTimeout()
50 void TCP::getMAC(char* dest)
54 strcpy(ifr.ifr_name, "eth0");
55 ioctl(sock, SIOCGIFHWADDR, &ifr);
56 memcpy(dest, ifr.ifr_hwaddr.sa_data, 6);
58 //TODO: Get MAC Address for windows
59 PIP_ADAPTER_INFO daptinfo=NULL;
61 GetAdaptersInfo(daptinfo,&size);
62 daptinfo=(PIP_ADAPTER_INFO)new char[size+1];
63 memcpy(dest,"ABCDEF", 6);//Dummy Address
64 sockaddr_in sock_address;
65 int sockname_len=sizeof(sock_address);
66 getsockname(sock,(sockaddr*)&sock_address,&sockname_len);
67 ULONG sockip=sock_address.sin_addr.s_addr;
68 if (GetAdaptersInfo(daptinfo,&size)==ERROR_SUCCESS)
70 PIP_ADAPTER_INFO daptinfo_it=daptinfo;
71 while (daptinfo_it!=NULL)
73 ULONG ipaddress=inet_addr(daptinfo_it->IpAddressList.IpAddress.String);
74 if (ipaddress==sockip)
76 memcpy(dest,daptinfo_it->Address, 6);
79 daptinfo_it=daptinfo_it->Next;
80 if (daptinfo_it==daptinfo) break;
92 int TCP::connectTo(char* host, unsigned short port)
94 sock = socket(PF_INET, SOCK_STREAM, 0);
95 if (sock == -1) return 0;
97 struct sockaddr_in dest_addr;
98 dest_addr.sin_family = AF_INET;
99 dest_addr.sin_port = htons(port);
102 if (!inet_aton(host, &dest_addr.sin_addr))
104 dest_addr.sin_addr.s_addr = inet_addr(host);
105 if (dest_addr.sin_addr.s_addr == INADDR_NONE)
112 memset(&(dest_addr.sin_zero), '\0', 8);
116 int oldflags = fcntl (sock, F_GETFL, 0);
117 oldflags |= O_NONBLOCK;
118 fcntl(sock, F_SETFL, oldflags);
120 unsigned long flag=1;
121 ioctlsocket(sock,FIONBIO,&flag);
125 // setReceiveWindow(2048);
127 // ok, how to open a connection in non blocking mode (and therefore have a self set timeout!!)
129 int success = connect(sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr));
131 if (success == 0) // if by some miracle the connection succeeded in no time flat, just return!
137 // first check errno for EINPROGRESS, otherwise it's a fail
138 // this doesn't work?
140 if (errno != EINPROGRESS)
142 int wsalasterr = WSAGetLastError();
143 if ((wsalasterr != WSAEWOULDBLOCK) && (wsalasterr != WSAEINPROGRESS))
150 // now do a timeout wait on writability on the socket
153 struct timeval timeout;
154 FD_ZERO(&connectSet);
155 FD_SET(sock, &connectSet);
158 success = select(sock + 1, NULL, &connectSet, NULL, &timeout);
166 // so the socket became available for writing. Contrary to expectation, this doesn't actually
167 // mean it connected...
170 socklen_t soErrorSize = sizeof(soError);
171 int gso = getsockopt(sock, SOL_SOCKET, SO_ERROR,(char*) &soError, &soErrorSize);
173 if ((gso == 0) && (soError == 0))
186 The full documentation:
189 The socket is non-blocking and the connection canĀ
190 not be completed immediately. It is possible to
191 select(2) or poll(2) for completion by selecting
192 the socket for writing. After select indicates
193 writability, use getsockopt(2) to read the SO_ERROR
194 option at level SOL_SOCKET to determine whether
195 connect completed successfully (SO_ERROR is zero)
196 or unsuccessfully (SO_ERROR is one of the usual
197 error codes listed here, explaining the reason for
202 void TCP::setReceiveWindow(size_t rxBufferSize)
204 // Set receive window
205 int r = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&rxBufferSize, sizeof(size_t));
206 Log::getInstance()->log("TCP", Log::DEBUG, "Set receive window to %i, success(=0): %i", rxBufferSize, r);
209 void TCP::assignSocket(int tsocket)
214 int TCP::isConnected()
219 int TCP::sendPacket(void* bufR, size_t count)
221 size_t bytes_sent = 0;
225 unsigned char* buf = (unsigned char*)bufR;
227 while (bytes_sent < count)
232 temp_write = this_write = write(sock, buf, count - bytes_sent);
233 // Log::getInstance()->log("TCP", Log::DEBUG, "TCP has written %i bytes", temp_write);
234 } while ( (this_write < 0) && (errno == EINTR) );
236 temp_write = this_write = send(sock,(char*) buf, count- bytes_sent,0);
237 } while ( (this_write == SOCKET_ERROR) && (WSAGetLastError() == WSAEINTR) );
243 bytes_sent += this_write;
249 UCHAR* TCP::receivePacket()
254 success = readData((UCHAR*)&packetLength, sizeof(int));
255 if (!success) return NULL;
257 packetLength = ntohl(packetLength);
259 if (packetLength > 500000)
261 Log::getInstance()->log("TCP", Log::ERR, "Received packet > 500000");
264 if (packetLength == 0)
266 Log::getInstance()->log("TCP", Log::ERR, "Received packet len = 0");
270 UCHAR* buffer = (UCHAR*) malloc(packetLength);
272 success = readData(buffer, packetLength);
276 Log::getInstance()->log("TCP", Log::ERR, "readData failed");
283 dataLength = packetLength;
287 int TCP::getDataLength()
292 int TCP::readData(UCHAR* buffer, int totalBytes)
300 struct timeval timeout;
301 struct timeval* passToSelect;
303 if (timeoutEnabled) passToSelect = &timeout;
304 else passToSelect = NULL;
309 FD_SET(sock, &readSet);
312 success = select(sock + 1, &readSet, NULL, NULL, passToSelect);
315 Log::getInstance()->log("TCP", Log::ERR, "Error or timeout");
316 return 0; // error, or timeout
319 thisRead = read(sock, &buffer[bytesRead], totalBytes - bytesRead);
321 thisRead = recv(sock,(char*) &buffer[bytesRead],totalBytes - bytesRead, 0);
323 // printf("read %i\n", thisRead);
326 // if read returns 0 then connection is closed
327 // in non-blocking mode if read is called with no data available, it returns -1
328 // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
329 Log::getInstance()->log("TCP", Log::ERR, "Detected connection closed");
333 bytesRead += thisRead;
335 if (bytesRead == totalBytes)
341 if (++readTries == 100)
343 // Log::getInstance()->log("TCP", Log::ERR, "Too many reads");
350 void TCP::dump(unsigned char* data, ULONG size)
352 printf("Size = %lu\n", size);
359 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",
360 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
361 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15],
362 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]),
363 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]));
371 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",
372 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
373 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14],
374 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]),
375 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]));
379 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",
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],
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]));
387 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",
388 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
389 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12],
390 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]),
391 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]));
395 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",
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],
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]));
403 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %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],
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]));
411 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %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],
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]));
419 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %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],
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]),
427 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %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 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 printf(" %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c\n",
434 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6],
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]));
439 printf(" %02X %02X %02X %02X %02X %02X %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],
441 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]));
445 printf(" %02X %02X %02X %02X %02X %c%c%c%c%c\n",
446 data[c], data[c+1], data[c+2], data[c+3], data[c+4],
447 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]));
451 printf(" %02X %02X %02X %02X %c%c%c%c\n",
452 data[c], data[c+1], data[c+2], data[c+3],
453 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]));
457 printf(" %02X %02X %02X %c%c%c\n",
458 data[c], data[c+1], data[c+2],
459 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]));
463 printf(" %02X %02X %c%c\n",
465 dcc(data[c]), dcc(data[c+1]));
479 UCHAR TCP::dcc(UCHAR c)
481 if (isspace(c)) return ' ';
482 if (isprint(c)) return c;