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);
76 size_t rxBufferSize = 2048;
77 setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &rxBufferSize, sizeof(size_t));
79 // ok, how to open a connection in non blocking mode (and therefore have a self set timeout!!)
81 int success = connect(sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr));
83 if (success == 0) // if by some miracle the connection succeeded in no time flat, just return!
89 // first check errno for EINPROGRESS, otherwise it's a fail
91 if (errno != EINPROGRESS)
97 // now do a timeout wait on writability on the socket
100 struct timeval timeout;
101 FD_ZERO(&connectSet);
102 FD_SET(sock, &connectSet);
105 success = select(sock + 1, NULL, &connectSet, NULL, &timeout);
113 // so the socket became available for writing. Contrary to expectation, this doesn't actually
114 // mean it connected...
117 socklen_t soErrorSize = sizeof(soError);
118 int gso = getsockopt(sock, SOL_SOCKET, SO_ERROR, &soError, &soErrorSize);
120 if ((gso == 0) && (soError == 0))
133 The full documentation:
136 The socket is non-blocking and the connection canĀ
137 not be completed immediately. It is possible to
138 select(2) or poll(2) for completion by selecting
139 the socket for writing. After select indicates
140 writability, use getsockopt(2) to read the SO_ERROR
141 option at level SOL_SOCKET to determine whether
142 connect completed successfully (SO_ERROR is zero)
143 or unsuccessfully (SO_ERROR is one of the usual
144 error codes listed here, explaining the reason for
149 void TCP::assignSocket(int tsocket)
154 int TCP::isConnected()
159 int TCP::sendPacket(void* bufR, size_t count)
161 size_t bytes_sent = 0;
165 unsigned char* buf = (unsigned char*)bufR;
167 while (bytes_sent < count)
171 temp_write = this_write = write(sock, buf, count - bytes_sent);
172 // Log::getInstance()->log("TCP", Log::DEBUG, "TCP has written %i bytes", temp_write);
173 } while ( (this_write < 0) && (errno == EINTR) );
180 bytes_sent += this_write;
186 UCHAR* TCP::receivePacket()
191 success = readData((UCHAR*)&packetLength, sizeof(int));
192 if (!success) return NULL;
194 packetLength = ntohl(packetLength);
196 if (packetLength > 500000)
198 Log::getInstance()->log("TCP", Log::ERR, "Received packet > 500000");
201 if (packetLength == 0)
203 Log::getInstance()->log("TCP", Log::ERR, "Received packet len = 0");
207 UCHAR* buffer = (UCHAR*) malloc(packetLength);
209 success = readData(buffer, packetLength);
213 Log::getInstance()->log("TCP", Log::ERR, "readData failed");
220 dataLength = packetLength;
224 int TCP::getDataLength()
229 int TCP::readData(UCHAR* buffer, int totalBytes)
237 struct timeval timeout;
238 struct timeval* passToSelect;
240 if (timeoutEnabled) passToSelect = &timeout;
241 else passToSelect = NULL;
246 FD_SET(sock, &readSet);
249 success = select(sock + 1, &readSet, NULL, NULL, passToSelect);
252 Log::getInstance()->log("TCP", Log::ERR, "Error or timeout");
253 return 0; // error, or timeout
256 thisRead = read(sock, &buffer[bytesRead], totalBytes - bytesRead);
257 // printf("read %i\n", thisRead);
260 // if read returns 0 then connection is closed
261 // in non-blocking mode if read is called with no data available, it returns -1
262 // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
263 Log::getInstance()->log("TCP", Log::ERR, "Detected connection closed");
267 bytesRead += thisRead;
269 if (bytesRead == totalBytes)
275 if (++readTries == 100)
277 // Log::getInstance()->log("TCP", Log::ERR, "Too many reads");
284 void TCP::dump(unsigned char* data, ULONG size)
286 printf("Size = %lu\n", size);
293 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",
294 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
295 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15],
296 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]),
297 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]));
305 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",
306 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
307 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14],
308 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]),
309 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]));
313 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",
314 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
315 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13],
316 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]),
317 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]));
321 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",
322 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
323 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12],
324 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]),
325 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]));
329 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",
330 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
331 data[c+8], data[c+9], data[c+10], data[c+11],
332 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]),
333 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]));
337 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %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],
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]));
345 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %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],
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]));
353 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %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],
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]),
361 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %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 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]));
367 printf(" %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c\n",
368 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6],
369 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]));
373 printf(" %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c\n",
374 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5],
375 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]));
379 printf(" %02X %02X %02X %02X %02X %c%c%c%c%c\n",
380 data[c], data[c+1], data[c+2], data[c+3], data[c+4],
381 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]));
385 printf(" %02X %02X %02X %02X %c%c%c%c\n",
386 data[c], data[c+1], data[c+2], data[c+3],
387 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]));
391 printf(" %02X %02X %02X %c%c%c\n",
392 data[c], data[c+1], data[c+2],
393 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]));
397 printf(" %02X %02X %c%c\n",
399 dcc(data[c]), dcc(data[c+1]));
413 UCHAR TCP::dcc(UCHAR c)
415 if (isspace(c)) return ' ';
416 if (isprint(c)) return c;