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);
245 // printf("read %i\n", thisRead);
248 // if read returns 0 then connection is closed
249 // in non-blocking mode if read is called with no data available, it returns -1
250 // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
251 Log::getInstance()->log("TCP", Log::ERR, "Detected connection closed");
255 bytesRead += thisRead;
257 if (bytesRead == totalBytes)
263 if (++readTries == 100)
265 // Log::getInstance()->log("TCP", Log::ERR, "Too many reads");
272 void TCP::dump(unsigned char* data, ULONG size)
274 printf("Size = %lu\n", size);
281 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",
282 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
283 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15],
284 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]),
285 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]));
293 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",
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],
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]));
301 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",
302 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
303 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13],
304 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]),
305 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]));
309 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",
310 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
311 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12],
312 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]),
313 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]));
317 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",
318 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
319 data[c+8], data[c+9], data[c+10], data[c+11],
320 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]),
321 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]));
325 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %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],
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]));
333 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c\n",
334 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
335 data[c+8], data[c+9],
336 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]),
337 dcc(data[c+8]), dcc(data[c+9]));
341 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c\n",
342 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
344 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 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c\n",
350 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
351 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]));
355 printf(" %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c\n",
356 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6],
357 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]));
361 printf(" %02X %02X %02X %02X %02X %02X %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],
363 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]));
367 printf(" %02X %02X %02X %02X %02X %c%c%c%c%c\n",
368 data[c], data[c+1], data[c+2], data[c+3], data[c+4],
369 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]));
373 printf(" %02X %02X %02X %02X %c%c%c%c\n",
374 data[c], data[c+1], data[c+2], data[c+3],
375 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]));
379 printf(" %02X %02X %02X %c%c%c\n",
380 data[c], data[c+1], data[c+2],
381 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]));
385 printf(" %02X %02X %c%c\n",
387 dcc(data[c]), dcc(data[c+1]));
401 UCHAR TCP::dcc(UCHAR c)
403 if (isspace(c)) return ' ';
404 if (isprint(c)) return c;