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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26 log = Log::getInstance();
29 readTimeoutEnabled = 1;
30 pthread_mutex_init(&sendLock, NULL);
41 if (connected) cleanup();
49 log->log("TCP", Log::DEBUG, "TCP has closed socket");
53 void TCP::disableReadTimeout()
55 readTimeoutEnabled = 0;
58 int TCP::connectTo(char* host, unsigned short port)
60 sock = socket(PF_INET, SOCK_STREAM, 0);
61 if (sock == -1) return 0;
63 struct sockaddr_in dest_addr;
64 dest_addr.sin_family = AF_INET;
65 dest_addr.sin_port = htons(port);
67 if (!inet_aton(host, &dest_addr.sin_addr))
73 memset(&(dest_addr.sin_zero), '\0', 8);
75 int success = connect(sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr));
86 void TCP::setNonBlocking()
88 int oldflags = fcntl(sock, F_GETFL, 0);
89 oldflags |= O_NONBLOCK;
90 fcntl(sock, F_SETFL, oldflags);
93 int TCP::setSoKeepTime(int timeOut)
99 s1 = setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &option, sizeof(option));
100 log->log("TCP", Log::DEBUG, "SO_KEEPALIVE = %i", s1);
103 s2 = setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, &option, sizeof(option));
104 log->log("TCP", Log::DEBUG, "TCP_KEEPIDLE = %i", s2);
106 s3 = setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, &option, sizeof(option));
107 log->log("TCP", Log::DEBUG, "TCP_KEEPINTVL = %i", s3);
110 s4 = setsockopt(sock, SOL_TCP, TCP_KEEPCNT, &option, sizeof(option));
111 log->log("TCP", Log::DEBUG, "TCP_KEEPCNT = %i", s4);
113 if (s1 || s2 || s3 || s4) return 0;
117 void TCP::assignSocket(int tsocket)
123 int TCP::isConnected()
129 UCHAR* TCP::receivePacket()
131 if (!connected) return NULL;
136 success = readData((UCHAR*)&packetLength, sizeof(int));
143 packetLength = ntohl(packetLength);
145 if (packetLength > 200000) return NULL;
146 UCHAR* buffer = (UCHAR*) malloc(packetLength);
148 success = readData(buffer, packetLength);
156 // dump((unsigned char*)buffer, packetLength);
158 dataLength = packetLength;
163 int TCP::getDataLength()
168 int TCP::readData(UCHAR* buffer, int totalBytes)
170 if (!connected) return 0;
177 struct timeval timeout;
178 struct timeval* passToSelect;
180 if (readTimeoutEnabled) passToSelect = &timeout;
181 else passToSelect = NULL;
186 FD_SET(sock, &readSet);
189 success = select(sock + 1, &readSet, NULL, NULL, passToSelect);
193 log->log("TCP", Log::DEBUG, "Select finished with %i", success);
194 return 0; // error, or timeout
197 thisRead = read(sock, &buffer[bytesRead], totalBytes - bytesRead);
200 // if read returns 0 then connection is closed
201 // in non-blocking mode if read is called with no data available, it returns -1
202 // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
206 bytesRead += thisRead;
208 // log->log("TCP", Log::DEBUG, "Bytes read now: %u", bytesRead);
209 if (bytesRead == totalBytes)
215 if (++readTries == 100)
218 log->log("TCP", Log::DEBUG, "too many reads");
225 int TCP::sendPacket(UCHAR* buf, size_t count)
227 pthread_mutex_lock(&sendLock);
231 pthread_mutex_unlock(&sendLock);
235 unsigned int bytesWritten = 0;
240 struct timeval timeout;
245 FD_SET(sock, &writeSet);
248 success = select(sock + 1, NULL, &writeSet, NULL, &timeout);
252 log->log("TCP", Log::DEBUG, "TCP: error or timeout");
253 pthread_mutex_unlock(&sendLock);
254 return 0; // error, or timeout
257 thisWrite = write(sock, &buf[bytesWritten], count - bytesWritten);
258 // log->log("TCP", Log::DEBUG, "written %i", thisWrite);
261 // if write returns 0 then connection is closed ?
262 // in non-blocking mode if read is called with no data available, it returns -1
263 // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
265 log->log("TCP", Log::DEBUG, "Detected connection closed");
266 pthread_mutex_unlock(&sendLock);
269 bytesWritten += thisWrite;
271 // log->log("TCP", Log::DEBUG, "Bytes written now: %u", bytesWritten);
272 if (bytesWritten == count)
274 pthread_mutex_unlock(&sendLock);
279 if (++writeTries == 100)
282 log->log("TCP", Log::DEBUG, "too many writes");
283 pthread_mutex_unlock(&sendLock);
290 void TCP::dump(unsigned char* data, USHORT size)
292 printf("Size = %u\n", size);
299 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",
300 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
301 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15],
302 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]),
303 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]));
311 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",
312 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
313 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14],
314 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]),
315 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]));
319 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",
320 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
321 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13],
322 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]),
323 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]));
327 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",
328 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
329 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12],
330 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]),
331 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]));
335 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",
336 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
337 data[c+8], data[c+9], data[c+10], data[c+11],
338 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]),
339 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]));
343 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c\n",
344 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
345 data[c+8], data[c+9], data[c+10],
346 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]),
347 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]));
351 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c\n",
352 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
353 data[c+8], data[c+9],
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]), dcc(data[c+7]),
355 dcc(data[c+8]), dcc(data[c+9]));
359 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%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], data[c+7],
362 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 %02X %c%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], data[c+7],
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]), dcc(data[c+7]));
373 printf(" %02X %02X %02X %02X %02X %02X %02X %c%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], data[c+6],
375 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]));
379 printf(" %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c\n",
380 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5],
381 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]));
385 printf(" %02X %02X %02X %02X %02X %c%c%c%c%c\n",
386 data[c], data[c+1], data[c+2], data[c+3], data[c+4],
387 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]));
391 printf(" %02X %02X %02X %02X %c%c%c%c\n",
392 data[c], data[c+1], data[c+2], data[c+3],
393 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]));
397 printf(" %02X %02X %02X %c%c%c\n",
398 data[c], data[c+1], data[c+2],
399 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]));
403 printf(" %02X %02X %c%c\n",
405 dcc(data[c]), dcc(data[c+1]));
419 unsigned char TCP::dcc(UCHAR c)
421 if (isspace(c)) return ' ';
422 if (isprint(c)) return c;