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 int TCP::connectTo(char* host, unsigned short port)
47 sock = socket(PF_INET, SOCK_STREAM, 0);
48 if (sock == -1) return 0;
50 struct sockaddr_in dest_addr;
51 dest_addr.sin_family = AF_INET;
52 dest_addr.sin_port = htons(port);
54 if (!inet_aton(host, &dest_addr.sin_addr))
60 memset(&(dest_addr.sin_zero), '\0', 8);
63 int oldflags = fcntl (sock, F_GETFL, 0);
64 oldflags |= O_NONBLOCK;
65 fcntl(sock, F_SETFL, oldflags);
67 // ok, how to open a connection in non blocking mode (and therefore have a self set timeout!!)
69 int success = connect(sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr));
71 if (success == 0) // if by some miracle the connection succeeded in no time flat, just return!
77 // first check errno for EINPROGRESS, otherwise it's a fail
79 if (errno != EINPROGRESS)
85 // now do a timeout wait on writability on the socket
88 struct timeval timeout;
90 FD_SET(sock, &connectSet);
93 success = select(sock + 1, NULL, &connectSet, NULL, &timeout);
101 // so the socket became available for writing. Contrary to expectation, this doesn't actually
102 // mean it connected...
105 socklen_t soErrorSize = sizeof(soError);
106 int gso = getsockopt(sock, SOL_SOCKET, SO_ERROR, &soError, &soErrorSize);
108 if ((gso == 0) && (soError == 0))
121 The full documentation:
124 The socket is non-blocking and the connection canĀ
125 not be completed immediately. It is possible to
126 select(2) or poll(2) for completion by selecting
127 the socket for writing. After select indicates
128 writability, use getsockopt(2) to read the SO_ERROR
129 option at level SOL_SOCKET to determine whether
130 connect completed successfully (SO_ERROR is zero)
131 or unsuccessfully (SO_ERROR is one of the usual
132 error codes listed here, explaining the reason for
137 void TCP::assignSocket(int tsocket)
142 int TCP::isConnected()
147 int TCP::sendPacket(void* bufR, size_t count)
149 size_t bytes_sent = 0;
153 unsigned char* buf = (unsigned char*)bufR;
155 while (bytes_sent < count)
159 temp_write = this_write = write(sock, buf, count - bytes_sent);
160 // Log::getInstance()->log("TCP", Log::DEBUG, "TCP has written %i bytes", temp_write);
161 } while ( (this_write < 0) && (errno == EINTR) );
168 bytes_sent += this_write;
174 UCHAR* TCP::receivePacket()
179 success = readData((UCHAR*)&packetLength, sizeof(int));
180 if (!success) return NULL;
182 packetLength = ntohl(packetLength);
184 if (packetLength > 500000)
186 Log::getInstance()->log("TCP", Log::ERR, "Received packet > 500000");
189 if (packetLength == 0)
191 Log::getInstance()->log("TCP", Log::ERR, "Received packet len = 0");
195 UCHAR* buffer = (UCHAR*) malloc(packetLength);
197 success = readData(buffer, packetLength);
201 Log::getInstance()->log("TCP", Log::ERR, "readData failed");
208 dataLength = packetLength;
212 int TCP::getDataLength()
217 int TCP::readData(UCHAR* buffer, int totalBytes)
225 struct timeval timeout;
226 struct timeval* passToSelect;
228 if (timeoutEnabled) passToSelect = &timeout;
229 else passToSelect = NULL;
234 FD_SET(sock, &readSet);
237 success = select(sock + 1, &readSet, NULL, NULL, passToSelect);
240 Log::getInstance()->log("TCP", Log::ERR, "Error or timeout");
241 return 0; // error, or timeout
244 thisRead = read(sock, &buffer[bytesRead], totalBytes - bytesRead);
247 // if read returns 0 then connection is closed
248 // in non-blocking mode if read is called with no data available, it returns -1
249 // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
250 Log::getInstance()->log("TCP", Log::ERR, "Detected connection closed");
254 bytesRead += thisRead;
256 if (bytesRead == totalBytes)
262 if (++readTries == 100)
264 Log::getInstance()->log("TCP", Log::ERR, "Too many reads");
271 void TCP::dump(unsigned char* data, ULONG size)
273 printf("Size = %lu\n", size);
280 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",
281 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
282 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15],
283 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]),
284 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]));
292 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",
293 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
294 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14],
295 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]),
296 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]));
300 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",
301 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
302 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13],
303 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]),
304 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]));
308 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",
309 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
310 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12],
311 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]),
312 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]));
316 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",
317 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
318 data[c+8], data[c+9], data[c+10], data[c+11],
319 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]),
320 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]));
324 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c\n",
325 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
326 data[c+8], data[c+9], data[c+10],
327 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]),
328 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]));
332 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c\n",
333 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
334 data[c+8], data[c+9],
335 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]),
336 dcc(data[c+8]), dcc(data[c+9]));
340 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c\n",
341 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
343 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]),
348 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c\n",
349 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
350 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 printf(" %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c\n",
355 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6],
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]));
360 printf(" %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c\n",
361 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5],
362 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]));
366 printf(" %02X %02X %02X %02X %02X %c%c%c%c%c\n",
367 data[c], data[c+1], data[c+2], data[c+3], data[c+4],
368 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]));
372 printf(" %02X %02X %02X %02X %c%c%c%c\n",
373 data[c], data[c+1], data[c+2], data[c+3],
374 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]));
378 printf(" %02X %02X %02X %c%c%c\n",
379 data[c], data[c+1], data[c+2],
380 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]));
384 printf(" %02X %02X %c%c\n",
386 dcc(data[c]), dcc(data[c+1]));
400 UCHAR TCP::dcc(UCHAR c)
402 if (isspace(c)) return ' ';
403 if (isprint(c)) return c;