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);
256 log->log("TCP", Log::DEBUG, "written %i", thisWrite);
259 // if write returns 0 then connection is closed ?
260 // in non-blocking mode if read is called with no data available, it returns -1
261 // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
263 log->log("TCP", Log::DEBUG, "Detected connection closed");
264 pthread_mutex_unlock(&sendLock);
267 bytesWritten += thisWrite;
269 // log->log("TCP", Log::DEBUG, "Bytes written now: %u", bytesWritten);
270 if (bytesWritten == count)
272 pthread_mutex_unlock(&sendLock);
277 if (++writeTries == 100)
280 log->log("TCP", Log::DEBUG, "too many writes");
281 pthread_mutex_unlock(&sendLock);
288 void TCP::dump(unsigned char* data, USHORT size)
290 printf("Size = %u\n", size);
297 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",
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], data[c+15],
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]), dcc(data[c+15]));
309 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",
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], data[c+13], data[c+14],
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]), dcc(data[c+13]), dcc(data[c+14]));
317 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",
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], data[c+12], data[c+13],
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]), dcc(data[c+12]), dcc(data[c+13]));
325 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",
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], data[c+11], data[c+12],
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]), dcc(data[c+11]), dcc(data[c+12]));
333 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",
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], data[c+10], data[c+11],
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]), dcc(data[c+10]), dcc(data[c+11]));
341 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%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],
343 data[c+8], data[c+9], data[c+10],
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]),
345 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]));
349 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%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 data[c+8], data[c+9],
352 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 dcc(data[c+8]), dcc(data[c+9]));
357 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c\n",
358 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
360 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]),
365 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %c%c%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], data[c+6], data[c+7],
367 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]));
371 printf(" %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c\n",
372 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6],
373 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]));
377 printf(" %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c\n",
378 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5],
379 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]));
383 printf(" %02X %02X %02X %02X %02X %c%c%c%c%c\n",
384 data[c], data[c+1], data[c+2], data[c+3], data[c+4],
385 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]));
389 printf(" %02X %02X %02X %02X %c%c%c%c\n",
390 data[c], data[c+1], data[c+2], data[c+3],
391 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]));
395 printf(" %02X %02X %02X %c%c%c\n",
396 data[c], data[c+1], data[c+2],
397 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]));
401 printf(" %02X %02X %c%c\n",
403 dcc(data[c]), dcc(data[c+1]));
417 unsigned char TCP::dcc(UCHAR c)
419 if (isspace(c)) return ' ';
420 if (isprint(c)) return c;