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)
48 strcpy(ifr.ifr_name, "eth0");
49 ioctl(sock, SIOCGIFHWADDR, &ifr);
50 memcpy(dest, ifr.ifr_hwaddr.sa_data, 6);
53 int TCP::connectTo(char* host, unsigned short port)
55 sock = socket(PF_INET, SOCK_STREAM, 0);
56 if (sock == -1) return 0;
58 struct sockaddr_in dest_addr;
59 dest_addr.sin_family = AF_INET;
60 dest_addr.sin_port = htons(port);
62 if (!inet_aton(host, &dest_addr.sin_addr))
68 memset(&(dest_addr.sin_zero), '\0', 8);
71 int oldflags = fcntl (sock, F_GETFL, 0);
72 oldflags |= O_NONBLOCK;
73 fcntl(sock, F_SETFL, oldflags);
75 // setReceiveWindow(2048);
77 // ok, how to open a connection in non blocking mode (and therefore have a self set timeout!!)
79 int success = connect(sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr));
81 if (success == 0) // if by some miracle the connection succeeded in no time flat, just return!
87 // first check errno for EINPROGRESS, otherwise it's a fail
89 if (errno != EINPROGRESS)
95 // now do a timeout wait on writability on the socket
98 struct timeval timeout;
100 FD_SET(sock, &connectSet);
103 success = select(sock + 1, NULL, &connectSet, NULL, &timeout);
111 // so the socket became available for writing. Contrary to expectation, this doesn't actually
112 // mean it connected...
115 socklen_t soErrorSize = sizeof(soError);
116 int gso = getsockopt(sock, SOL_SOCKET, SO_ERROR, &soError, &soErrorSize);
118 if ((gso == 0) && (soError == 0))
131 The full documentation:
134 The socket is non-blocking and the connection canĀ
135 not be completed immediately. It is possible to
136 select(2) or poll(2) for completion by selecting
137 the socket for writing. After select indicates
138 writability, use getsockopt(2) to read the SO_ERROR
139 option at level SOL_SOCKET to determine whether
140 connect completed successfully (SO_ERROR is zero)
141 or unsuccessfully (SO_ERROR is one of the usual
142 error codes listed here, explaining the reason for
147 void TCP::setReceiveWindow(size_t rxBufferSize)
149 // Set receive window
150 int r = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &rxBufferSize, sizeof(size_t));
151 Log::getInstance()->log("TCP", Log::DEBUG, "Set receive window to %i, success(=0): %i", rxBufferSize, r);
154 void TCP::assignSocket(int tsocket)
159 int TCP::isConnected()
164 int TCP::sendPacket(void* bufR, size_t count)
166 size_t bytes_sent = 0;
170 unsigned char* buf = (unsigned char*)bufR;
172 while (bytes_sent < count)
176 temp_write = this_write = write(sock, buf, count - bytes_sent);
177 // Log::getInstance()->log("TCP", Log::DEBUG, "TCP has written %i bytes", temp_write);
178 } while ( (this_write < 0) && (errno == EINTR) );
185 bytes_sent += this_write;
191 UCHAR* TCP::receivePacket()
196 success = readData((UCHAR*)&packetLength, sizeof(int));
197 if (!success) return NULL;
199 packetLength = ntohl(packetLength);
201 if (packetLength > 500000)
203 Log::getInstance()->log("TCP", Log::ERR, "Received packet > 500000");
206 if (packetLength == 0)
208 Log::getInstance()->log("TCP", Log::ERR, "Received packet len = 0");
212 UCHAR* buffer = (UCHAR*) malloc(packetLength);
214 success = readData(buffer, packetLength);
218 Log::getInstance()->log("TCP", Log::ERR, "readData failed");
225 dataLength = packetLength;
229 int TCP::getDataLength()
234 int TCP::readData(UCHAR* buffer, int totalBytes)
242 struct timeval timeout;
243 struct timeval* passToSelect;
245 if (timeoutEnabled) passToSelect = &timeout;
246 else passToSelect = NULL;
251 FD_SET(sock, &readSet);
254 success = select(sock + 1, &readSet, NULL, NULL, passToSelect);
257 Log::getInstance()->log("TCP", Log::ERR, "Error or timeout");
258 return 0; // error, or timeout
261 thisRead = read(sock, &buffer[bytesRead], totalBytes - bytesRead);
262 // printf("read %i\n", thisRead);
265 // if read returns 0 then connection is closed
266 // in non-blocking mode if read is called with no data available, it returns -1
267 // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
268 Log::getInstance()->log("TCP", Log::ERR, "Detected connection closed");
272 bytesRead += thisRead;
274 if (bytesRead == totalBytes)
280 if (++readTries == 100)
282 // Log::getInstance()->log("TCP", Log::ERR, "Too many reads");
289 void TCP::dump(unsigned char* data, ULONG size)
291 printf("Size = %lu\n", size);
298 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",
299 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
300 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15],
301 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]),
302 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]));
310 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",
311 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
312 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14],
313 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]),
314 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]));
318 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",
319 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
320 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13],
321 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]),
322 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]));
326 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",
327 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
328 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12],
329 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]),
330 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]));
334 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",
335 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
336 data[c+8], data[c+9], data[c+10], data[c+11],
337 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]),
338 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]));
342 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c\n",
343 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
344 data[c+8], data[c+9], data[c+10],
345 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]),
346 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]));
350 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c\n",
351 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
352 data[c+8], data[c+9],
353 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]),
354 dcc(data[c+8]), dcc(data[c+9]));
358 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c\n",
359 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
361 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]),
366 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c\n",
367 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
368 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]));
372 printf(" %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c\n",
373 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6],
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]));
378 printf(" %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c\n",
379 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5],
380 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]));
384 printf(" %02X %02X %02X %02X %02X %c%c%c%c%c\n",
385 data[c], data[c+1], data[c+2], data[c+3], data[c+4],
386 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]));
390 printf(" %02X %02X %02X %02X %c%c%c%c\n",
391 data[c], data[c+1], data[c+2], data[c+3],
392 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]));
396 printf(" %02X %02X %02X %c%c%c\n",
397 data[c], data[c+1], data[c+2],
398 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]));
402 printf(" %02X %02X %c%c\n",
404 dcc(data[c]), dcc(data[c+1]));
418 UCHAR TCP::dcc(UCHAR c)
420 if (isspace(c)) return ' ';
421 if (isprint(c)) return c;