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
30 #define MUTEX_LOCK(mutex) pthread_mutex_lock(mutex)
31 #define MUTEX_UNLOCK(mutex) pthread_mutex_unlock(mutex)
33 #define MUTEX_LOCK(mutex) WaitForSingleObject(*(mutex), INFINITE )
34 #define MUTEX_UNLOCK(mutex) ReleaseMutex(*(mutex))
44 pthread_mutex_init(&mutex, NULL);
46 mutex=CreateMutex(NULL,FALSE,NULL);
55 Log::getInstance()->log("TCP", Log::DEBUG, "Have closed");
63 void TCP::disableTimeout()
68 void TCP::getMAC(char* dest)
72 strcpy(ifr.ifr_name, "eth0");
73 ioctl(sock, SIOCGIFHWADDR, &ifr);
74 memcpy(dest, ifr.ifr_hwaddr.sa_data, 6);
76 //TODO: Get MAC Address for windows
77 PIP_ADAPTER_INFO daptinfo=NULL;
79 GetAdaptersInfo(daptinfo,&size);
80 daptinfo=(PIP_ADAPTER_INFO)new char[size+1];
81 memcpy(dest,"ABCDEF", 6);//Dummy Address
82 sockaddr_in sock_address;
83 int sockname_len=sizeof(sock_address);
84 getsockname(sock,(sockaddr*)&sock_address,&sockname_len);
85 ULONG sockip=sock_address.sin_addr.s_addr;
86 if (GetAdaptersInfo(daptinfo,&size)==ERROR_SUCCESS)
88 PIP_ADAPTER_INFO daptinfo_it=daptinfo;
89 while (daptinfo_it!=NULL)
91 ULONG ipaddress=inet_addr(daptinfo_it->IpAddressList.IpAddress.String);
92 if (ipaddress==sockip)
94 memcpy(dest,daptinfo_it->Address, 6);
97 daptinfo_it=daptinfo_it->Next;
98 if (daptinfo_it==daptinfo) break;
110 int TCP::connectTo(char* host, unsigned short port)
112 sock = socket(PF_INET, SOCK_STREAM, 0);
113 if (sock == -1) return 0;
115 struct sockaddr_in dest_addr;
116 dest_addr.sin_family = AF_INET;
117 dest_addr.sin_port = htons(port);
120 if (!inet_aton(host, &dest_addr.sin_addr))
122 dest_addr.sin_addr.s_addr = inet_addr(host);
123 if (dest_addr.sin_addr.s_addr == INADDR_NONE)
130 memset(&(dest_addr.sin_zero), '\0', 8);
134 int oldflags = fcntl (sock, F_GETFL, 0);
135 oldflags |= O_NONBLOCK;
136 fcntl(sock, F_SETFL, oldflags);
138 unsigned long flag=1;
139 ioctlsocket(sock,FIONBIO,&flag);
143 // setReceiveWindow(2048);
145 // ok, how to open a connection in non blocking mode (and therefore have a self set timeout!!)
147 int success = connect(sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr));
149 if (success == 0) // if by some miracle the connection succeeded in no time flat, just return!
155 // first check errno for EINPROGRESS, otherwise it's a fail
156 // this doesn't work?
158 if (errno != EINPROGRESS)
160 int wsalasterr = WSAGetLastError();
161 if ((wsalasterr != WSAEWOULDBLOCK) && (wsalasterr != WSAEINPROGRESS))
168 // now do a timeout wait on writability on the socket
171 struct timeval timeout;
172 FD_ZERO(&connectSet);
173 FD_SET(sock, &connectSet);
176 success = select(sock + 1, NULL, &connectSet, NULL, &timeout);
184 // so the socket became available for writing. Contrary to expectation, this doesn't actually
185 // mean it connected...
188 socklen_t soErrorSize = sizeof(soError);
189 int gso = getsockopt(sock, SOL_SOCKET, SO_ERROR,(char*) &soError, &soErrorSize);
191 if ((gso == 0) && (soError == 0))
204 The full documentation:
207 The socket is non-blocking and the connection canĀ
208 not be completed immediately. It is possible to
209 select(2) or poll(2) for completion by selecting
210 the socket for writing. After select indicates
211 writability, use getsockopt(2) to read the SO_ERROR
212 option at level SOL_SOCKET to determine whether
213 connect completed successfully (SO_ERROR is zero)
214 or unsuccessfully (SO_ERROR is one of the usual
215 error codes listed here, explaining the reason for
220 void TCP::setReceiveWindow(size_t rxBufferSize)
222 // Set receive window
223 int r = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&rxBufferSize, sizeof(size_t));
224 Log::getInstance()->log("TCP", Log::DEBUG, "Set receive window to %i, success(=0): %i", rxBufferSize, r);
227 void TCP::assignSocket(int tsocket)
232 int TCP::isConnected()
237 int TCP::sendData(void* bufR, size_t count)
239 size_t bytes_sent = 0;
243 unsigned char* buf = (unsigned char*)bufR;
247 while (bytes_sent < count)
252 temp_write = this_write = write(sock, buf, count - bytes_sent);
253 // Log::getInstance()->log("TCP", Log::DEBUG, "TCP has written %i bytes", temp_write);
254 } while ( (this_write < 0) && (errno == EINTR) );
256 temp_write = this_write = send(sock,(char*) buf, count- bytes_sent,0);
257 } while ( (this_write == SOCKET_ERROR) && (WSAGetLastError() == WSAEINTR) );
261 MUTEX_UNLOCK(&mutex);
264 bytes_sent += this_write;
268 MUTEX_UNLOCK(&mutex);
273 int TCP::readData(UCHAR* buffer, int totalBytes)
281 struct timeval timeout;
282 struct timeval* passToSelect;
284 if (timeoutEnabled) passToSelect = &timeout;
285 else passToSelect = NULL;
290 FD_SET(sock, &readSet);
293 success = select(sock + 1, &readSet, NULL, NULL, passToSelect);
296 return 0; // error, or timeout
299 thisRead = read(sock, &buffer[bytesRead], totalBytes - bytesRead);
301 thisRead = recv(sock, (char*)&buffer[bytesRead], totalBytes - bytesRead, 0);
303 //Log::getInstance()->log("TCP", Log::DEBUG, "Read %i", thisRead);
306 // if read returns 0 then connection is closed
307 // in non-blocking mode if read is called with no data available, it returns -1
308 // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
309 Log::getInstance()->log("TCP", Log::ERR, "Detected connection closed");
314 bytesRead += thisRead;
315 if (bytesRead == totalBytes)
321 if (++readTries == 100)
323 Log::getInstance()->log("TCP", Log::ERR, "Too many reads");
330 void TCP::dump(unsigned char* data, ULONG size)
332 printf("Size = %lu\n", size);
339 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",
340 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
341 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15],
342 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]),
343 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]));
351 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",
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], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14],
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]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]), dcc(data[c+14]));
359 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",
360 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
361 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13],
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]),
363 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]));
367 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",
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 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12],
370 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 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]));
375 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",
376 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
377 data[c+8], data[c+9], data[c+10], data[c+11],
378 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]),
379 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]));
383 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c\n",
384 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
385 data[c+8], data[c+9], data[c+10],
386 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]),
387 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]));
391 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c\n",
392 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
393 data[c+8], data[c+9],
394 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]),
395 dcc(data[c+8]), dcc(data[c+9]));
399 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c\n",
400 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
402 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]),
407 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c\n",
408 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
409 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]));
413 printf(" %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c\n",
414 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6],
415 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]));
419 printf(" %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c\n",
420 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5],
421 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]));
425 printf(" %02X %02X %02X %02X %02X %c%c%c%c%c\n",
426 data[c], data[c+1], data[c+2], data[c+3], data[c+4],
427 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]));
431 printf(" %02X %02X %02X %02X %c%c%c%c\n",
432 data[c], data[c+1], data[c+2], data[c+3],
433 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]));
437 printf(" %02X %02X %02X %c%c%c\n",
438 data[c], data[c+1], data[c+2],
439 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]));
443 printf(" %02X %02X %c%c\n",
445 dcc(data[c]), dcc(data[c+1]));
459 UCHAR TCP::dcc(UCHAR c)
461 if (isspace(c)) return ' ';
462 if (isprint(c)) return c;