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* buf, size_t count)
149 size_t bytes_sent = 0;
153 while (bytes_sent < count)
157 temp_write = this_write = write(sock, buf, count - bytes_sent);
158 // Log::getInstance()->log("TCP", Log::DEBUG, "TCP has written %i bytes", temp_write);
159 } while ( (this_write < 0) && (errno == EINTR) );
166 bytes_sent += this_write;
167 (unsigned char*)buf += this_write;
172 UCHAR* TCP::receivePacket()
177 success = readData((UCHAR*)&packetLength, sizeof(int));
178 if (!success) return NULL;
180 packetLength = ntohl(packetLength);
182 if (packetLength > 200000)
184 Log::getInstance()->log("TCP", Log::ERR, "Received packet > 200000");
187 if (packetLength == 0)
189 Log::getInstance()->log("TCP", Log::ERR, "Received packet len = 0");
193 UCHAR* buffer = (UCHAR*) malloc(packetLength);
195 success = readData(buffer, packetLength);
199 Log::getInstance()->log("TCP", Log::ERR, "readData failed");
206 dataLength = packetLength;
210 int TCP::getDataLength()
215 int TCP::readData(UCHAR* buffer, int totalBytes)
223 struct timeval timeout;
224 struct timeval* passToSelect;
226 if (timeoutEnabled) passToSelect = &timeout;
227 else passToSelect = NULL;
232 FD_SET(sock, &readSet);
235 success = select(sock + 1, &readSet, NULL, NULL, passToSelect);
238 Log::getInstance()->log("TCP", Log::ERR, "Error or timeout");
239 return 0; // error, or timeout
242 thisRead = read(sock, &buffer[bytesRead], totalBytes - bytesRead);
245 // if read returns 0 then connection is closed
246 // in non-blocking mode if read is called with no data available, it returns -1
247 // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
248 Log::getInstance()->log("TCP", Log::ERR, "Detected connection closed");
252 bytesRead += thisRead;
254 if (bytesRead == totalBytes)
260 if (++readTries == 100)
262 Log::getInstance()->log("TCP", Log::ERR, "Too many reads");
269 void TCP::dump(unsigned char* data, ULONG size)
271 printf("Size = %lu\n", size);
278 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",
279 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
280 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15],
281 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]),
282 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]));
290 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",
291 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
292 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14],
293 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]),
294 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]));
298 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",
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],
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]));
306 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",
307 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
308 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12],
309 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]),
310 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]));
314 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",
315 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
316 data[c+8], data[c+9], data[c+10], data[c+11],
317 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]),
318 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]));
322 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c\n",
323 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
324 data[c+8], data[c+9], data[c+10],
325 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]),
326 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]));
330 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c\n",
331 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
332 data[c+8], data[c+9],
333 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]),
334 dcc(data[c+8]), dcc(data[c+9]));
338 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c\n",
339 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
341 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 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c\n",
347 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]));
352 printf(" %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c\n",
353 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6],
354 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]));
358 printf(" %02X %02X %02X %02X %02X %02X %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],
360 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]));
364 printf(" %02X %02X %02X %02X %02X %c%c%c%c%c\n",
365 data[c], data[c+1], data[c+2], data[c+3], data[c+4],
366 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]));
370 printf(" %02X %02X %02X %02X %c%c%c%c\n",
371 data[c], data[c+1], data[c+2], data[c+3],
372 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]));
376 printf(" %02X %02X %02X %c%c%c\n",
377 data[c], data[c+1], data[c+2],
378 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]));
382 printf(" %02X %02X %c%c\n",
384 dcc(data[c]), dcc(data[c+1]));
398 UCHAR TCP::dcc(UCHAR c)
400 if (isspace(c)) return ' ';
401 if (isprint(c)) return c;