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
39 Log::getInstance()->log("TCP", Log::DEBUG, "Have closed");
43 void TCP::disableTimeout()
48 void TCP::getMAC(char* dest)
52 strcpy(ifr.ifr_name, "eth0");
53 ioctl(sock, SIOCGIFHWADDR, &ifr);
54 memcpy(dest, ifr.ifr_hwaddr.sa_data, 6);
56 //TODO: Get MAC Address for windows
57 PIP_ADAPTER_INFO daptinfo=NULL;
59 GetAdaptersInfo(daptinfo,&size);
60 daptinfo=(PIP_ADAPTER_INFO)new char[size+1];
61 memcpy(dest,"ABCDEF", 6);//Dummy Address
62 sockaddr_in sock_address;
63 int sockname_len=sizeof(sock_address);
64 getsockname(sock,(sockaddr*)&sock_address,&sockname_len);
65 ULONG sockip=sock_address.sin_addr.s_addr;
66 if (GetAdaptersInfo(daptinfo,&size)==ERROR_SUCCESS)
68 PIP_ADAPTER_INFO daptinfo_it=daptinfo;
69 while (daptinfo_it!=NULL)
71 ULONG ipaddress=inet_addr(daptinfo_it->IpAddressList.IpAddress.String);
72 if (ipaddress==sockip)
74 memcpy(dest,daptinfo_it->Address, 6);
77 daptinfo_it=daptinfo_it->Next;
78 if (daptinfo_it==daptinfo) break;
90 int TCP::connectTo(char* host, unsigned short port)
92 sock = socket(PF_INET, SOCK_STREAM, 0);
93 if (sock == -1) return 0;
95 struct sockaddr_in dest_addr;
96 dest_addr.sin_family = AF_INET;
97 dest_addr.sin_port = htons(port);
100 if (!inet_aton(host, &dest_addr.sin_addr))
102 dest_addr.sin_addr.s_addr = inet_addr(host);
103 if (dest_addr.sin_addr.s_addr == INADDR_NONE)
110 memset(&(dest_addr.sin_zero), '\0', 8);
114 int oldflags = fcntl (sock, F_GETFL, 0);
115 oldflags |= O_NONBLOCK;
116 fcntl(sock, F_SETFL, oldflags);
118 unsigned long flag=1;
119 ioctlsocket(sock,FIONBIO,&flag);
123 // setReceiveWindow(2048);
125 // ok, how to open a connection in non blocking mode (and therefore have a self set timeout!!)
127 int success = connect(sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr));
129 if (success == 0) // if by some miracle the connection succeeded in no time flat, just return!
135 // first check errno for EINPROGRESS, otherwise it's a fail
136 // this doesn't work?
138 if (errno != EINPROGRESS)
140 int wsalasterr = WSAGetLastError();
141 if ((wsalasterr != WSAEWOULDBLOCK) && (wsalasterr != WSAEINPROGRESS))
148 // now do a timeout wait on writability on the socket
151 struct timeval timeout;
152 FD_ZERO(&connectSet);
153 FD_SET(sock, &connectSet);
156 success = select(sock + 1, NULL, &connectSet, NULL, &timeout);
164 // so the socket became available for writing. Contrary to expectation, this doesn't actually
165 // mean it connected...
168 socklen_t soErrorSize = sizeof(soError);
169 int gso = getsockopt(sock, SOL_SOCKET, SO_ERROR,(char*) &soError, &soErrorSize);
171 if ((gso == 0) && (soError == 0))
184 The full documentation:
187 The socket is non-blocking and the connection canĀ
188 not be completed immediately. It is possible to
189 select(2) or poll(2) for completion by selecting
190 the socket for writing. After select indicates
191 writability, use getsockopt(2) to read the SO_ERROR
192 option at level SOL_SOCKET to determine whether
193 connect completed successfully (SO_ERROR is zero)
194 or unsuccessfully (SO_ERROR is one of the usual
195 error codes listed here, explaining the reason for
200 void TCP::setReceiveWindow(size_t rxBufferSize)
202 // Set receive window
203 int r = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&rxBufferSize, sizeof(size_t));
204 Log::getInstance()->log("TCP", Log::DEBUG, "Set receive window to %i, success(=0): %i", rxBufferSize, r);
207 void TCP::assignSocket(int tsocket)
212 int TCP::isConnected()
217 int TCP::sendPacket(void* bufR, size_t count)
219 size_t bytes_sent = 0;
223 unsigned char* buf = (unsigned char*)bufR;
225 while (bytes_sent < count)
230 temp_write = this_write = write(sock, buf, count - bytes_sent);
231 // Log::getInstance()->log("TCP", Log::DEBUG, "TCP has written %i bytes", temp_write);
232 } while ( (this_write < 0) && (errno == EINTR) );
234 temp_write = this_write = send(sock,(char*) buf, count- bytes_sent,0);
235 } while ( (this_write == SOCKET_ERROR) && (WSAGetLastError() == WSAEINTR) );
241 bytes_sent += this_write;
247 UCHAR* TCP::receivePacket()
252 success = readData((UCHAR*)&packetLength, sizeof(int));
253 if (!success) return NULL;
255 packetLength = ntohl(packetLength);
257 if (packetLength > 500000)
259 Log::getInstance()->log("TCP", Log::ERR, "Received packet > 500000");
262 if (packetLength == 0)
264 Log::getInstance()->log("TCP", Log::ERR, "Received packet len = 0");
268 UCHAR* buffer = (UCHAR*) malloc(packetLength);
270 success = readData(buffer, packetLength);
274 Log::getInstance()->log("TCP", Log::ERR, "readData failed");
281 dataLength = packetLength;
285 int TCP::getDataLength()
290 int TCP::readData(UCHAR* buffer, int totalBytes)
298 struct timeval timeout;
299 struct timeval* passToSelect;
301 if (timeoutEnabled) passToSelect = &timeout;
302 else passToSelect = NULL;
307 FD_SET(sock, &readSet);
310 success = select(sock + 1, &readSet, NULL, NULL, passToSelect);
313 Log::getInstance()->log("TCP", Log::ERR, "Error or timeout");
314 return 0; // error, or timeout
317 thisRead = read(sock, &buffer[bytesRead], totalBytes - bytesRead);
319 thisRead = recv(sock,(char*) &buffer[bytesRead],totalBytes - bytesRead, 0);
321 // printf("read %i\n", thisRead);
324 // if read returns 0 then connection is closed
325 // in non-blocking mode if read is called with no data available, it returns -1
326 // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
327 Log::getInstance()->log("TCP", Log::ERR, "Detected connection closed");
331 bytesRead += thisRead;
333 if (bytesRead == totalBytes)
339 if (++readTries == 100)
341 // Log::getInstance()->log("TCP", Log::ERR, "Too many reads");
348 void TCP::dump(unsigned char* data, ULONG size)
350 printf("Size = %lu\n", size);
357 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",
358 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
359 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15],
360 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]),
361 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]));
369 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",
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], data[c+11], data[c+12], data[c+13], data[c+14],
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]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]), dcc(data[c+14]));
377 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",
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], data[c+10], data[c+11], data[c+12], data[c+13],
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]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]));
385 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",
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],
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]));
393 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",
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 data[c+8], data[c+9], data[c+10], data[c+11],
396 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]),
397 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]));
401 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c\n",
402 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
403 data[c+8], data[c+9], data[c+10],
404 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]),
405 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]));
409 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c\n",
410 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
411 data[c+8], data[c+9],
412 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]),
413 dcc(data[c+8]), dcc(data[c+9]));
417 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c\n",
418 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
420 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 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c\n",
426 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
427 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 printf(" %02X %02X %02X %02X %02X %02X %02X %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],
433 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]));
437 printf(" %02X %02X %02X %02X %02X %02X %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],
439 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]));
443 printf(" %02X %02X %02X %02X %02X %c%c%c%c%c\n",
444 data[c], data[c+1], data[c+2], data[c+3], data[c+4],
445 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]));
449 printf(" %02X %02X %02X %02X %c%c%c%c\n",
450 data[c], data[c+1], data[c+2], data[c+3],
451 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]));
455 printf(" %02X %02X %02X %c%c%c\n",
456 data[c], data[c+1], data[c+2],
457 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]));
461 printf(" %02X %02X %c%c\n",
463 dcc(data[c]), dcc(data[c+1]));
477 UCHAR TCP::dcc(UCHAR c)
479 if (isspace(c)) return ' ';
480 if (isprint(c)) return c;