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;
40 if (connected) cleanup();
48 log->log("TCP", Log::DEBUG, "TCP has closed socket");
52 void TCP::disableReadTimeout()
54 readTimeoutEnabled = 0;
57 int TCP::connectTo(char* host, unsigned short port)
59 sock = socket(PF_INET, SOCK_STREAM, 0);
60 if (sock == -1) return 0;
62 struct sockaddr_in dest_addr;
63 dest_addr.sin_family = AF_INET;
64 dest_addr.sin_port = htons(port);
66 if (!inet_aton(host, &dest_addr.sin_addr))
72 memset(&(dest_addr.sin_zero), '\0', 8);
74 int success = connect(sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr));
85 void TCP::setNonBlocking()
87 int oldflags = fcntl(sock, F_GETFL, 0);
88 oldflags |= O_NONBLOCK;
89 fcntl(sock, F_SETFL, oldflags);
92 int TCP::setSoKeepTime(int timeOut)
98 s1 = setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &option, sizeof(option));
99 log->log("TCP", Log::DEBUG, "SO_KEEPALIVE = %i", s1);
102 s2 = setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, &option, sizeof(option));
103 log->log("TCP", Log::DEBUG, "TCP_KEEPIDLE = %i", s2);
105 s3 = setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, &option, sizeof(option));
106 log->log("TCP", Log::DEBUG, "TCP_KEEPINTVL = %i", s3);
109 s4 = setsockopt(sock, SOL_TCP, TCP_KEEPCNT, &option, sizeof(option));
110 log->log("TCP", Log::DEBUG, "TCP_KEEPCNT = %i", s4);
112 if (s1 || s2 || s3 || s4) return 0;
116 void TCP::assignSocket(int tsocket)
122 int TCP::isConnected()
127 UCHAR* TCP::receivePacket()
129 if (!connected) return NULL;
134 success = readData((UCHAR*)&packetLength, sizeof(int));
141 packetLength = ntohl(packetLength);
143 if (packetLength > 200000) return NULL;
144 UCHAR* buffer = (UCHAR*) malloc(packetLength);
146 success = readData(buffer, packetLength);
154 // dump((unsigned char*)buffer, packetLength);
156 dataLength = packetLength;
160 int TCP::getDataLength()
165 int TCP::readData(UCHAR* buffer, int totalBytes)
167 if (!connected) return 0;
174 struct timeval timeout;
175 struct timeval* passToSelect;
177 if (readTimeoutEnabled) passToSelect = &timeout;
178 else passToSelect = NULL;
183 FD_SET(sock, &readSet);
186 success = select(sock + 1, &readSet, NULL, NULL, passToSelect);
190 log->log("TCP", Log::DEBUG, "TCP: error or timeout");
191 return 0; // error, or timeout
194 thisRead = read(sock, &buffer[bytesRead], totalBytes - bytesRead);
197 // if read returns 0 then connection is closed
198 // in non-blocking mode if read is called with no data available, it returns -1
199 // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
203 bytesRead += thisRead;
205 // log->log("TCP", Log::DEBUG, "Bytes read now: %u", bytesRead);
206 if (bytesRead == totalBytes)
212 if (++readTries == 100)
215 log->log("TCP", Log::DEBUG, "too many reads");
222 int TCP::sendPacket(UCHAR* buf, size_t count)
224 if (!connected) return 0;
226 unsigned int bytesWritten = 0;
231 struct timeval timeout;
236 FD_SET(sock, &writeSet);
239 success = select(sock + 1, NULL, &writeSet, NULL, &timeout);
243 log->log("TCP", Log::DEBUG, "TCP: error or timeout");
244 return 0; // error, or timeout
247 thisWrite = write(sock, &buf[bytesWritten], count - bytesWritten);
250 // if write returns 0 then connection is closed ?
251 // in non-blocking mode if read is called with no data available, it returns -1
252 // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
254 log->log("TCP", Log::DEBUG, "Detected connection closed");
257 bytesWritten += thisWrite;
259 // log->log("TCP", Log::DEBUG, "Bytes written now: %u", bytesWritten);
260 if (bytesWritten == count)
266 if (++writeTries == 100)
269 log->log("TCP", Log::DEBUG, "too many writes");
279 void TCP::dump(unsigned char* data, USHORT size)
281 printf("Size = %u\n", size);
288 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",
289 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
290 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15],
291 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]),
292 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]));
300 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",
301 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
302 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14],
303 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]),
304 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]));
308 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",
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],
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]));
316 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",
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],
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]));
324 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",
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],
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]));
332 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %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],
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]));
340 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %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],
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]));
348 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %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],
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]),
356 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %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],
358 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]));
362 printf(" %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c\n",
363 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6],
364 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]));
368 printf(" %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c\n",
369 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5],
370 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]));
374 printf(" %02X %02X %02X %02X %02X %c%c%c%c%c\n",
375 data[c], data[c+1], data[c+2], data[c+3], data[c+4],
376 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]));
380 printf(" %02X %02X %02X %02X %c%c%c%c\n",
381 data[c], data[c+1], data[c+2], data[c+3],
382 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]));
386 printf(" %02X %02X %02X %c%c%c\n",
387 data[c], data[c+1], data[c+2],
388 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]));
392 printf(" %02X %02X %c%c\n",
394 dcc(data[c]), dcc(data[c+1]));
408 unsigned char TCP::dcc(UCHAR c)
410 if (isspace(c)) return ' ';
411 if (isprint(c)) return c;