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.
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;
242 unsigned char* buf = (unsigned char*)bufR;
246 while (bytes_sent < count)
251 this_write = write(sock, buf, count - bytes_sent);
252 // Log::getInstance()->log("TCP", Log::DEBUG, "TCP has written %i bytes", this_write);
253 } while ( (this_write < 0) && (errno == EINTR) );
255 this_write = send(sock,(char*) buf, count- bytes_sent,0);
256 } while ( (this_write == SOCKET_ERROR) && (WSAGetLastError() == WSAEINTR) );
260 MUTEX_UNLOCK(&mutex);
263 bytes_sent += this_write;
267 MUTEX_UNLOCK(&mutex);
272 int TCP::readData(UCHAR* buffer, int totalBytes)
280 struct timeval timeout;
281 struct timeval* passToSelect;
283 if (timeoutEnabled) passToSelect = &timeout;
284 else passToSelect = NULL;
289 FD_SET(sock, &readSet);
292 // Log::getInstance()->log("TCP", Log::DEBUG, "Going to select");
293 success = select(sock + 1, &readSet, NULL, NULL, passToSelect);
294 // Log::getInstance()->log("TCP", Log::DEBUG, "Back from select with success = %i", success);
297 return 0; // error, or timeout
300 thisRead = read(sock, &buffer[bytesRead], totalBytes - bytesRead);
302 thisRead = recv(sock, (char*)&buffer[bytesRead], totalBytes - bytesRead, 0);
304 //Log::getInstance()->log("TCP", Log::DEBUG, "Read %i", thisRead);
307 // if read returns 0 then connection is closed
308 // in non-blocking mode if read is called with no data available, it returns -1
309 // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
310 Log::getInstance()->log("TCP", Log::ERR, "Detected connection closed");
315 bytesRead += thisRead;
316 if (bytesRead == totalBytes)
322 if (++readTries == 1000)
324 Log::getInstance()->log("TCP", Log::ERR, "Too many reads");
331 void TCP::dump(unsigned char* data, ULONG size)
333 printf("Size = %lu\n", size);
340 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",
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], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15],
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]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]), dcc(data[c+14]), dcc(data[c+15]));
352 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",
353 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
354 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14],
355 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 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]));
360 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",
361 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
362 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13],
363 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 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]));
368 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",
369 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
370 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12],
371 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]),
372 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]));
376 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",
377 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
378 data[c+8], data[c+9], data[c+10], data[c+11],
379 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]),
380 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]));
384 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c\n",
385 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
386 data[c+8], data[c+9], data[c+10],
387 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]),
388 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]));
392 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c\n",
393 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
394 data[c+8], data[c+9],
395 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]),
396 dcc(data[c+8]), dcc(data[c+9]));
400 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c\n",
401 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
403 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]),
408 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c\n",
409 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
410 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]));
414 printf(" %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c\n",
415 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6],
416 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]));
420 printf(" %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c\n",
421 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5],
422 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]));
426 printf(" %02X %02X %02X %02X %02X %c%c%c%c%c\n",
427 data[c], data[c+1], data[c+2], data[c+3], data[c+4],
428 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]));
432 printf(" %02X %02X %02X %02X %c%c%c%c\n",
433 data[c], data[c+1], data[c+2], data[c+3],
434 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]));
438 printf(" %02X %02X %02X %c%c%c\n",
439 data[c], data[c+1], data[c+2],
440 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]));
444 printf(" %02X %02X %c%c\n",
446 dcc(data[c]), dcc(data[c+1]));
460 UCHAR TCP::dcc(UCHAR c)
462 if (isspace(c)) return ' ';
463 if (isprint(c)) return c;