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;
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 // Log::getInstance()->log("TCP", Log::DEBUG, "Going to select");
294 success = select(sock + 1, &readSet, NULL, NULL, passToSelect);
295 // Log::getInstance()->log("TCP", Log::DEBUG, "Back from select with success = %i", success);
298 return 0; // error, or timeout
301 thisRead = read(sock, &buffer[bytesRead], totalBytes - bytesRead);
303 thisRead = recv(sock, (char*)&buffer[bytesRead], totalBytes - bytesRead, 0);
305 //Log::getInstance()->log("TCP", Log::DEBUG, "Read %i", thisRead);
308 // if read returns 0 then connection is closed
309 // in non-blocking mode if read is called with no data available, it returns -1
310 // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
311 Log::getInstance()->log("TCP", Log::ERR, "Detected connection closed");
316 bytesRead += thisRead;
317 if (bytesRead == totalBytes)
323 if (++readTries == 100)
325 Log::getInstance()->log("TCP", Log::ERR, "Too many reads");
332 void TCP::dump(unsigned char* data, ULONG size)
334 printf("Size = %lu\n", size);
341 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",
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], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15],
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]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]), dcc(data[c+14]), dcc(data[c+15]));
353 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",
354 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
355 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14],
356 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]),
357 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]));
361 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",
362 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
363 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13],
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]), dcc(data[c+7]),
365 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]));
369 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",
370 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
371 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12],
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]), dcc(data[c+7]),
373 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]));
377 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",
378 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
379 data[c+8], data[c+9], data[c+10], data[c+11],
380 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]),
381 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]));
385 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c\n",
386 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
387 data[c+8], data[c+9], data[c+10],
388 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]),
389 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]));
393 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c\n",
394 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
395 data[c+8], data[c+9],
396 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]),
397 dcc(data[c+8]), dcc(data[c+9]));
401 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c\n",
402 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
404 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]),
409 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c\n",
410 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
411 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]));
415 printf(" %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c\n",
416 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6],
417 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]));
421 printf(" %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c\n",
422 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5],
423 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]));
427 printf(" %02X %02X %02X %02X %02X %c%c%c%c%c\n",
428 data[c], data[c+1], data[c+2], data[c+3], data[c+4],
429 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]));
433 printf(" %02X %02X %02X %02X %c%c%c%c\n",
434 data[c], data[c+1], data[c+2], data[c+3],
435 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]));
439 printf(" %02X %02X %02X %c%c%c\n",
440 data[c], data[c+1], data[c+2],
441 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]));
445 printf(" %02X %02X %c%c\n",
447 dcc(data[c]), dcc(data[c+1]));
461 UCHAR TCP::dcc(UCHAR c)
463 if (isspace(c)) return ' ';
464 if (isprint(c)) return c;