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
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()
128 UCHAR* TCP::receivePacket()
130 if (!connected) return NULL;
135 success = readData((UCHAR*)&packetLength, sizeof(int));
142 packetLength = ntohl(packetLength);
144 if (packetLength > 200000) return NULL;
145 UCHAR* buffer = (UCHAR*) malloc(packetLength);
147 success = readData(buffer, packetLength);
155 // dump((unsigned char*)buffer, packetLength);
157 dataLength = packetLength;
161 int TCP::getDataLength()
166 int TCP::readData(UCHAR* buffer, int totalBytes)
168 if (!connected) return 0;
175 struct timeval timeout;
176 struct timeval* passToSelect;
178 if (readTimeoutEnabled) passToSelect = &timeout;
179 else passToSelect = NULL;
184 FD_SET(sock, &readSet);
187 success = select(sock + 1, &readSet, NULL, NULL, passToSelect);
191 log->log("TCP", Log::DEBUG, "TCP: error or timeout");
192 return 0; // error, or timeout
195 thisRead = read(sock, &buffer[bytesRead], totalBytes - bytesRead);
198 // if read returns 0 then connection is closed
199 // in non-blocking mode if read is called with no data available, it returns -1
200 // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
204 bytesRead += thisRead;
206 // log->log("TCP", Log::DEBUG, "Bytes read now: %u", bytesRead);
207 if (bytesRead == totalBytes)
213 if (++readTries == 100)
216 log->log("TCP", Log::DEBUG, "too many reads");
223 int TCP::sendPacket(UCHAR* buf, size_t count)
225 pthread_mutex_lock(&sendLock);
229 pthread_mutex_unlock(&sendLock);
233 unsigned int bytesWritten = 0;
238 struct timeval timeout;
243 FD_SET(sock, &writeSet);
246 success = select(sock + 1, NULL, &writeSet, NULL, &timeout);
250 log->log("TCP", Log::DEBUG, "TCP: error or timeout");
251 pthread_mutex_unlock(&sendLock);
252 return 0; // error, or timeout
255 thisWrite = write(sock, &buf[bytesWritten], count - bytesWritten);
258 // if write returns 0 then connection is closed ?
259 // in non-blocking mode if read is called with no data available, it returns -1
260 // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
262 log->log("TCP", Log::DEBUG, "Detected connection closed");
263 pthread_mutex_unlock(&sendLock);
266 bytesWritten += thisWrite;
268 // log->log("TCP", Log::DEBUG, "Bytes written now: %u", bytesWritten);
269 if (bytesWritten == count)
271 pthread_mutex_unlock(&sendLock);
276 if (++writeTries == 100)
279 log->log("TCP", Log::DEBUG, "too many writes");
280 pthread_mutex_unlock(&sendLock);
287 void TCP::dump(unsigned char* data, USHORT size)
289 printf("Size = %u\n", size);
296 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",
297 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
298 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15],
299 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]),
300 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]));
308 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",
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], data[c+13], data[c+14],
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]), dcc(data[c+13]), dcc(data[c+14]));
316 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",
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], data[c+12], data[c+13],
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]), dcc(data[c+12]), dcc(data[c+13]));
324 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",
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], data[c+11], data[c+12],
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]), dcc(data[c+11]), dcc(data[c+12]));
332 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",
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], data[c+10], data[c+11],
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]), dcc(data[c+10]), dcc(data[c+11]));
340 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%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],
342 data[c+8], data[c+9], data[c+10],
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]),
344 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]));
348 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%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 data[c+8], data[c+9],
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]),
352 dcc(data[c+8]), dcc(data[c+9]));
356 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c\n",
357 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
359 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]),
364 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c\n",
365 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
366 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]));
370 printf(" %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c\n",
371 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6],
372 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]));
376 printf(" %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c\n",
377 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5],
378 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]));
382 printf(" %02X %02X %02X %02X %02X %c%c%c%c%c\n",
383 data[c], data[c+1], data[c+2], data[c+3], data[c+4],
384 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]));
388 printf(" %02X %02X %02X %02X %c%c%c%c\n",
389 data[c], data[c+1], data[c+2], data[c+3],
390 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]));
394 printf(" %02X %02X %02X %c%c%c\n",
395 data[c], data[c+1], data[c+2],
396 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]));
400 printf(" %02X %02X %c%c\n",
402 dcc(data[c]), dcc(data[c+1]));
416 unsigned char TCP::dcc(UCHAR c)
418 if (isspace(c)) return ' ';
419 if (isprint(c)) return c;