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
36 Log::getInstance()->log("TCP", Log::DEBUG, "Have closed");
40 void TCP::disableTimeout()
45 void TCP::getMAC(char* dest)
49 strcpy(ifr.ifr_name, "eth0");
50 ioctl(sock, SIOCGIFHWADDR, &ifr);
51 memcpy(dest, ifr.ifr_hwaddr.sa_data, 6);
53 //TODO: Get MAC Address for windows
54 memcpy(dest, "ABCDEF", 6);
58 int TCP::connectTo(char* host, unsigned short port)
60 sock = socket(PF_INET, SOCK_STREAM, 0);
61 if (sock == -1) return 0;
63 struct sockaddr_in dest_addr;
64 dest_addr.sin_family = AF_INET;
65 dest_addr.sin_port = htons(port);
68 if (!inet_aton(host, &dest_addr.sin_addr))
70 dest_addr.sin_addr.s_addr = inet_addr(host);
71 if (dest_addr.sin_addr.s_addr == INADDR_NONE)
78 memset(&(dest_addr.sin_zero), '\0', 8);
82 int oldflags = fcntl (sock, F_GETFL, 0);
83 oldflags |= O_NONBLOCK;
84 fcntl(sock, F_SETFL, oldflags);
87 ioctlsocket(sock,FIONBIO,&flag);
91 // setReceiveWindow(2048);
93 // ok, how to open a connection in non blocking mode (and therefore have a self set timeout!!)
95 int success = connect(sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr));
97 if (success == 0) // if by some miracle the connection succeeded in no time flat, just return!
103 // first check errno for EINPROGRESS, otherwise it's a fail
104 // this doesn't work?
106 if (errno != EINPROGRESS)
108 int wsalasterr = WSAGetLastError();
109 if ((wsalasterr != WSAEWOULDBLOCK) && (wsalasterr != WSAEINPROGRESS))
116 // now do a timeout wait on writability on the socket
119 struct timeval timeout;
120 FD_ZERO(&connectSet);
121 FD_SET(sock, &connectSet);
124 success = select(sock + 1, NULL, &connectSet, NULL, &timeout);
132 // so the socket became available for writing. Contrary to expectation, this doesn't actually
133 // mean it connected...
136 socklen_t soErrorSize = sizeof(soError);
137 int gso = getsockopt(sock, SOL_SOCKET, SO_ERROR,(char*) &soError, &soErrorSize);
139 if ((gso == 0) && (soError == 0))
152 The full documentation:
155 The socket is non-blocking and the connection canĀ
156 not be completed immediately. It is possible to
157 select(2) or poll(2) for completion by selecting
158 the socket for writing. After select indicates
159 writability, use getsockopt(2) to read the SO_ERROR
160 option at level SOL_SOCKET to determine whether
161 connect completed successfully (SO_ERROR is zero)
162 or unsuccessfully (SO_ERROR is one of the usual
163 error codes listed here, explaining the reason for
168 void TCP::setReceiveWindow(size_t rxBufferSize)
170 // Set receive window
171 int r = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&rxBufferSize, sizeof(size_t));
172 Log::getInstance()->log("TCP", Log::DEBUG, "Set receive window to %i, success(=0): %i", rxBufferSize, r);
175 void TCP::assignSocket(int tsocket)
180 int TCP::isConnected()
185 int TCP::sendPacket(void* bufR, size_t count)
187 size_t bytes_sent = 0;
191 unsigned char* buf = (unsigned char*)bufR;
193 while (bytes_sent < count)
198 temp_write = this_write = write(sock, buf, count - bytes_sent);
199 // Log::getInstance()->log("TCP", Log::DEBUG, "TCP has written %i bytes", temp_write);
200 } while ( (this_write < 0) && (errno == EINTR) );
202 temp_write = this_write = send(sock,(char*) buf, count- bytes_sent,0);
203 } while ( (this_write == SOCKET_ERROR) && (WSAGetLastError() == WSAEINTR) );
209 bytes_sent += this_write;
215 UCHAR* TCP::receivePacket()
220 success = readData((UCHAR*)&packetLength, sizeof(int));
221 if (!success) return NULL;
223 packetLength = ntohl(packetLength);
225 if (packetLength > 500000)
227 Log::getInstance()->log("TCP", Log::ERR, "Received packet > 500000");
230 if (packetLength == 0)
232 Log::getInstance()->log("TCP", Log::ERR, "Received packet len = 0");
236 UCHAR* buffer = (UCHAR*) malloc(packetLength);
238 success = readData(buffer, packetLength);
242 Log::getInstance()->log("TCP", Log::ERR, "readData failed");
249 dataLength = packetLength;
253 int TCP::getDataLength()
258 int TCP::readData(UCHAR* buffer, int totalBytes)
266 struct timeval timeout;
267 struct timeval* passToSelect;
269 if (timeoutEnabled) passToSelect = &timeout;
270 else passToSelect = NULL;
275 FD_SET(sock, &readSet);
278 success = select(sock + 1, &readSet, NULL, NULL, passToSelect);
281 Log::getInstance()->log("TCP", Log::ERR, "Error or timeout");
282 return 0; // error, or timeout
285 thisRead = read(sock, &buffer[bytesRead], totalBytes - bytesRead);
287 thisRead = recv(sock,(char*) &buffer[bytesRead],totalBytes - bytesRead, 0);
289 // printf("read %i\n", thisRead);
292 // if read returns 0 then connection is closed
293 // in non-blocking mode if read is called with no data available, it returns -1
294 // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
295 Log::getInstance()->log("TCP", Log::ERR, "Detected connection closed");
299 bytesRead += thisRead;
301 if (bytesRead == totalBytes)
307 if (++readTries == 100)
309 // Log::getInstance()->log("TCP", Log::ERR, "Too many reads");
316 void TCP::dump(unsigned char* data, ULONG size)
318 printf("Size = %lu\n", size);
325 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",
326 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
327 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15],
328 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]),
329 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]));
337 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",
338 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
339 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14],
340 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]),
341 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]));
345 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",
346 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
347 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13],
348 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]),
349 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]));
353 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",
354 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
355 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12],
356 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]),
357 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]));
361 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",
362 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
363 data[c+8], data[c+9], data[c+10], data[c+11],
364 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]),
365 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]));
369 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c\n",
370 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
371 data[c+8], data[c+9], data[c+10],
372 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]),
373 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]));
377 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c\n",
378 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
379 data[c+8], data[c+9],
380 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]),
381 dcc(data[c+8]), dcc(data[c+9]));
385 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %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],
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]),
393 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c\n",
394 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
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]));
399 printf(" %02X %02X %02X %02X %02X %02X %02X %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],
401 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]));
405 printf(" %02X %02X %02X %02X %02X %02X %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],
407 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]));
411 printf(" %02X %02X %02X %02X %02X %c%c%c%c%c\n",
412 data[c], data[c+1], data[c+2], data[c+3], data[c+4],
413 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]));
417 printf(" %02X %02X %02X %02X %c%c%c%c\n",
418 data[c], data[c+1], data[c+2], data[c+3],
419 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]));
423 printf(" %02X %02X %02X %c%c%c\n",
424 data[c], data[c+1], data[c+2],
425 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]));
429 printf(" %02X %02X %c%c\n",
431 dcc(data[c]), dcc(data[c+1]));
445 UCHAR TCP::dcc(UCHAR c)
447 if (isspace(c)) return ' ';
448 if (isprint(c)) return c;