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);
68 size_t rxBufferSize = 2048;
69 setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &rxBufferSize, sizeof(size_t));
71 // ok, how to open a connection in non blocking mode (and therefore have a self set timeout!!)
73 int success = connect(sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr));
75 if (success == 0) // if by some miracle the connection succeeded in no time flat, just return!
81 // first check errno for EINPROGRESS, otherwise it's a fail
83 if (errno != EINPROGRESS)
89 // now do a timeout wait on writability on the socket
92 struct timeval timeout;
94 FD_SET(sock, &connectSet);
97 success = select(sock + 1, NULL, &connectSet, NULL, &timeout);
105 // so the socket became available for writing. Contrary to expectation, this doesn't actually
106 // mean it connected...
109 socklen_t soErrorSize = sizeof(soError);
110 int gso = getsockopt(sock, SOL_SOCKET, SO_ERROR, &soError, &soErrorSize);
112 if ((gso == 0) && (soError == 0))
125 The full documentation:
128 The socket is non-blocking and the connection canĀ
129 not be completed immediately. It is possible to
130 select(2) or poll(2) for completion by selecting
131 the socket for writing. After select indicates
132 writability, use getsockopt(2) to read the SO_ERROR
133 option at level SOL_SOCKET to determine whether
134 connect completed successfully (SO_ERROR is zero)
135 or unsuccessfully (SO_ERROR is one of the usual
136 error codes listed here, explaining the reason for
141 void TCP::assignSocket(int tsocket)
146 int TCP::isConnected()
151 int TCP::sendPacket(void* bufR, size_t count)
153 size_t bytes_sent = 0;
157 unsigned char* buf = (unsigned char*)bufR;
159 while (bytes_sent < count)
163 temp_write = this_write = write(sock, buf, count - bytes_sent);
164 // Log::getInstance()->log("TCP", Log::DEBUG, "TCP has written %i bytes", temp_write);
165 } while ( (this_write < 0) && (errno == EINTR) );
172 bytes_sent += this_write;
178 UCHAR* TCP::receivePacket()
183 success = readData((UCHAR*)&packetLength, sizeof(int));
184 if (!success) return NULL;
186 packetLength = ntohl(packetLength);
188 if (packetLength > 500000)
190 Log::getInstance()->log("TCP", Log::ERR, "Received packet > 500000");
193 if (packetLength == 0)
195 Log::getInstance()->log("TCP", Log::ERR, "Received packet len = 0");
199 UCHAR* buffer = (UCHAR*) malloc(packetLength);
201 success = readData(buffer, packetLength);
205 Log::getInstance()->log("TCP", Log::ERR, "readData failed");
212 dataLength = packetLength;
216 int TCP::getDataLength()
221 int TCP::readData(UCHAR* buffer, int totalBytes)
229 struct timeval timeout;
230 struct timeval* passToSelect;
232 if (timeoutEnabled) passToSelect = &timeout;
233 else passToSelect = NULL;
238 FD_SET(sock, &readSet);
241 success = select(sock + 1, &readSet, NULL, NULL, passToSelect);
244 Log::getInstance()->log("TCP", Log::ERR, "Error or timeout");
245 return 0; // error, or timeout
248 thisRead = read(sock, &buffer[bytesRead], totalBytes - bytesRead);
249 // printf("read %i\n", thisRead);
252 // if read returns 0 then connection is closed
253 // in non-blocking mode if read is called with no data available, it returns -1
254 // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
255 Log::getInstance()->log("TCP", Log::ERR, "Detected connection closed");
259 bytesRead += thisRead;
261 if (bytesRead == totalBytes)
267 if (++readTries == 100)
269 // Log::getInstance()->log("TCP", Log::ERR, "Too many reads");
276 void TCP::dump(unsigned char* data, ULONG size)
278 printf("Size = %lu\n", size);
285 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",
286 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
287 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15],
288 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]),
289 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]));
297 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",
298 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
299 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14],
300 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]),
301 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]));
305 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",
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],
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]));
313 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",
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],
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]));
321 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",
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],
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]));
329 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %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],
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]));
337 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %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],
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]));
345 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %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],
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]),
353 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %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],
355 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]));
359 printf(" %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c\n",
360 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6],
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]));
365 printf(" %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c\n",
366 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5],
367 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]));
371 printf(" %02X %02X %02X %02X %02X %c%c%c%c%c\n",
372 data[c], data[c+1], data[c+2], data[c+3], data[c+4],
373 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]));
377 printf(" %02X %02X %02X %02X %c%c%c%c\n",
378 data[c], data[c+1], data[c+2], data[c+3],
379 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]));
383 printf(" %02X %02X %02X %c%c%c\n",
384 data[c], data[c+1], data[c+2],
385 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]));
389 printf(" %02X %02X %c%c\n",
391 dcc(data[c]), dcc(data[c+1]));
405 UCHAR TCP::dcc(UCHAR c)
407 if (isspace(c)) return ' ';
408 if (isprint(c)) return c;