]> git.vomp.tv Git - vompclient.git/blob - tcp.cc
Demuxer::scanForVideo()
[vompclient.git] / tcp.cc
1 /*
2     Copyright 2004-2005 Chris Tallon
3     Copyright 2003-2004 University Of Bradford
4
5     This file is part of VOMP.
6
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.
11
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.
16
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
20 */
21
22 #include "tcp.h"
23 #ifdef WIN32
24 #include <Iphlpapi.h>
25 #endif
26
27 TCP::TCP()
28 {
29   sock = 0;
30   connected = 0;
31   timeoutEnabled = 1;
32 }
33
34 TCP::~TCP()
35 {
36   if (connected)
37   {
38     CLOSESOCKET(sock);
39     Log::getInstance()->log("TCP", Log::DEBUG, "Have closed");
40   }
41 }
42
43 void TCP::disableTimeout()
44 {
45   timeoutEnabled = 0;
46 }
47
48 void TCP::getMAC(char* dest)
49 {
50 #ifndef WIN32
51   struct ifreq ifr;
52   strcpy(ifr.ifr_name, "eth0");
53   ioctl(sock, SIOCGIFHWADDR, &ifr);
54   memcpy(dest, ifr.ifr_hwaddr.sa_data, 6);
55 #else
56   //TODO: Get MAC Address for windows
57   PIP_ADAPTER_INFO daptinfo=NULL;
58   DWORD size=0;
59   GetAdaptersInfo(daptinfo,&size);
60   daptinfo=(PIP_ADAPTER_INFO)new char[size+1];
61   memcpy(dest,"ABCDEF", 6);//Dummy Address
62   sockaddr_in sock_address;
63   int sockname_len=sizeof(sock_address);
64   getsockname(sock,(sockaddr*)&sock_address,&sockname_len);
65   ULONG sockip=sock_address.sin_addr.s_addr;
66   if (GetAdaptersInfo(daptinfo,&size)==ERROR_SUCCESS)
67   {
68     PIP_ADAPTER_INFO daptinfo_it=daptinfo;
69     while (daptinfo_it!=NULL)
70     {
71       ULONG ipaddress=inet_addr(daptinfo_it->IpAddressList.IpAddress.String);
72       if (ipaddress==sockip)
73       { //Is it our MAC?
74         memcpy(dest,daptinfo_it->Address, 6);
75         break;
76       }
77       daptinfo_it=daptinfo_it->Next;
78       if (daptinfo_it==daptinfo) break;
79     }
80   }
81   else
82   {
83     // Marten?
84   }
85
86   delete [] daptinfo;
87 #endif
88 }
89
90 int TCP::connectTo(char* host, unsigned short port)
91 {
92   sock = socket(PF_INET, SOCK_STREAM, 0);
93   if (sock == -1) return 0;
94
95   struct sockaddr_in dest_addr;
96   dest_addr.sin_family = AF_INET;
97   dest_addr.sin_port = htons(port);
98
99 #ifndef WIN32
100   if (!inet_aton(host, &dest_addr.sin_addr))
101 #else
102   dest_addr.sin_addr.s_addr = inet_addr(host);
103   if (dest_addr.sin_addr.s_addr == INADDR_NONE)
104 #endif
105   {
106     CLOSESOCKET(sock);
107     return 0;
108   }
109
110   memset(&(dest_addr.sin_zero), '\0', 8);
111
112   // set non blocking
113 #ifndef WIN32
114   int oldflags = fcntl (sock, F_GETFL, 0);
115   oldflags |= O_NONBLOCK;
116   fcntl(sock, F_SETFL, oldflags);
117 #else
118   unsigned long flag=1;
119   ioctlsocket(sock,FIONBIO,&flag);
120
121 #endif
122
123 //  setReceiveWindow(2048);
124
125   // ok, how to open a connection in non blocking mode (and therefore have a self set timeout!!)
126
127   int success = connect(sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr));
128
129   if (success == 0)  // if by some miracle the connection succeeded in no time flat, just return!
130   {
131     connected = 1;
132     return 1;
133   }
134
135   // first check errno for EINPROGRESS, otherwise it's a fail
136   // this doesn't work?
137 #ifndef WIN32
138   if (errno != EINPROGRESS)
139 #else
140   int wsalasterr = WSAGetLastError();
141   if ((wsalasterr != WSAEWOULDBLOCK) && (wsalasterr != WSAEINPROGRESS))
142 #endif
143   {
144     CLOSESOCKET(sock);
145     return 0;
146   }
147
148   // now do a timeout wait on writability on the socket
149
150   fd_set connectSet;
151   struct timeval timeout;
152   FD_ZERO(&connectSet);
153   FD_SET(sock, &connectSet);
154   timeout.tv_sec = 10;
155   timeout.tv_usec = 0;
156   success = select(sock + 1, NULL, &connectSet, NULL, &timeout);
157   if (success < 1)
158   {
159     // timeout or error
160     CLOSESOCKET(sock);
161     return 0;
162   }
163
164   // so the socket became available for writing. Contrary to expectation, this doesn't actually
165   // mean it connected...
166
167   int soError;
168   socklen_t soErrorSize = sizeof(soError);
169   int gso = getsockopt(sock, SOL_SOCKET, SO_ERROR,(char*) &soError, &soErrorSize);
170
171   if ((gso == 0) && (soError == 0))
172   {
173     // success!
174     connected = 1;
175     return 1;
176   }
177   else
178   {
179     CLOSESOCKET(sock);
180     return 0;
181   }
182
183 /*
184 The full documentation:
185
186        EINPROGRESS
187               The  socket is non-blocking and the connection canĀ­
188               not be completed immediately.  It  is  possible  to
189               select(2)  or  poll(2)  for completion by selecting
190               the socket  for  writing.  After  select  indicates
191               writability, use getsockopt(2) to read the SO_ERROR
192               option at level  SOL_SOCKET  to  determine  whether
193               connect  completed  successfully (SO_ERROR is zero)
194               or unsuccessfully (SO_ERROR is  one  of  the  usual
195               error  codes listed here, explaining the reason for
196               the failure).
197 */
198 }
199
200 void TCP::setReceiveWindow(size_t rxBufferSize)
201 {
202   // Set receive window
203   int r = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&rxBufferSize, sizeof(size_t));
204   Log::getInstance()->log("TCP", Log::DEBUG, "Set receive window to %i, success(=0): %i", rxBufferSize, r);
205 }
206
207 void TCP::assignSocket(int tsocket)
208 {
209   sock = tsocket;
210 }
211
212 int TCP::isConnected()
213 {
214   return connected;
215 }
216
217 int TCP::sendPacket(void* bufR, size_t count)
218 {
219   size_t bytes_sent = 0;
220   int this_write;
221   int temp_write;
222
223   unsigned char* buf = (unsigned char*)bufR;
224
225   while (bytes_sent < count)
226   {
227     do
228     {
229 #ifndef WIN32
230       temp_write = this_write = write(sock, buf, count - bytes_sent);
231 //      Log::getInstance()->log("TCP", Log::DEBUG, "TCP has written %i bytes", temp_write);
232     } while ( (this_write < 0) && (errno == EINTR) );
233 #else
234       temp_write = this_write = send(sock,(char*) buf, count- bytes_sent,0);
235     } while ( (this_write == SOCKET_ERROR) && (WSAGetLastError() == WSAEINTR) );
236 #endif
237     if (this_write <= 0)
238     {
239       return(this_write);
240     }
241     bytes_sent += this_write;
242     buf += this_write;
243   }
244   return(count);
245 }
246
247 UCHAR* TCP::receivePacket()
248 {
249   ULONG packetLength;
250   int success;
251
252   success = readData((UCHAR*)&packetLength, sizeof(int));
253   if (!success) return NULL;
254
255   packetLength = ntohl(packetLength);
256
257   if (packetLength > 500000)
258   {
259     Log::getInstance()->log("TCP", Log::ERR, "Received packet > 500000");
260     return NULL;
261   }
262   if (packetLength == 0)
263   {
264     Log::getInstance()->log("TCP", Log::ERR, "Received packet len = 0");
265     return NULL;
266   }
267
268   UCHAR* buffer = (UCHAR*) malloc(packetLength);
269
270   success = readData(buffer, packetLength);
271
272   if (!success)
273   {
274     Log::getInstance()->log("TCP", Log::ERR, "readData failed");
275     free(buffer);
276     CLOSESOCKET(sock);
277     connected = 0;
278     return NULL;
279   }
280
281   dataLength = packetLength;
282   return buffer;
283 }
284
285 int TCP::getDataLength()
286 {
287   return dataLength;
288 }
289
290 int TCP::readData(UCHAR* buffer, int totalBytes)
291 {
292
293   int bytesRead = 0;
294   int thisRead;
295   int readTries = 0;
296   int success;
297   fd_set readSet;
298   struct timeval timeout;
299   struct timeval* passToSelect;
300
301   if (timeoutEnabled) passToSelect = &timeout;
302   else passToSelect = NULL;
303
304   while(1)
305   {
306     FD_ZERO(&readSet);
307     FD_SET(sock, &readSet);
308     timeout.tv_sec = 20;
309     timeout.tv_usec = 0;
310     success = select(sock + 1, &readSet, NULL, NULL, passToSelect);
311     if (success < 1)
312     {
313       Log::getInstance()->log("TCP", Log::ERR, "Error or timeout");
314       return 0;  // error, or timeout
315     }
316 #ifndef WIN32
317     thisRead = read(sock, &buffer[bytesRead], totalBytes - bytesRead);
318 #else
319     thisRead = recv(sock,(char*) &buffer[bytesRead],totalBytes - bytesRead, 0);
320 #endif
321 //    printf("read %i\n", thisRead);
322     if (!thisRead)
323     {
324       // if read returns 0 then connection is closed
325       // in non-blocking mode if read is called with no data available, it returns -1
326       // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
327       Log::getInstance()->log("TCP", Log::ERR, "Detected connection closed");
328       connected = 0;
329       return 0;
330     }
331     bytesRead += thisRead;
332
333     if (bytesRead == totalBytes)
334     {
335       return 1;
336     }
337     else
338     {
339       if (++readTries == 100)
340       {
341 //        Log::getInstance()->log("TCP", Log::ERR, "Too many reads");
342 //        return 0;
343       }
344     }
345   }
346 }
347
348 void TCP::dump(unsigned char* data, ULONG size)
349 {
350   printf("Size = %lu\n", size);
351
352   ULONG c = 0;
353   while(c < size)
354   {
355     if ((size - c) > 15)
356     {
357       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",
358         data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
359         data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15],
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]),
361         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]));
362       c += 16;
363     }
364     else
365     {
366       switch (size - c)
367       {
368         case 15:
369           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",
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], data[c+13], data[c+14],
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]), dcc(data[c+13]), dcc(data[c+14]));
374           c += 15;
375           break;
376         case 14:
377           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",
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], data[c+12], data[c+13],
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]), dcc(data[c+12]), dcc(data[c+13]));
382           c += 14;
383           break;
384         case 13:
385           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",
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], data[c+11], data[c+12],
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]), dcc(data[c+11]), dcc(data[c+12]));
390           c += 13;
391           break;
392         case 12:
393           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",
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], data[c+10], data[c+11],
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]), dcc(data[c+10]), dcc(data[c+11]));
398           c += 12;
399           break;
400         case 11:
401           printf(" %02X %02X %02X %02X  %02X %02X %02X %02X  %02X %02X %02X                  %c%c%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],
403             data[c+8], data[c+9], data[c+10],
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]),
405             dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]));
406           c += 11;
407           break;
408         case 10:
409           printf(" %02X %02X %02X %02X  %02X %02X %02X %02X  %02X %02X                     %c%c%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             data[c+8], data[c+9],
412             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             dcc(data[c+8]), dcc(data[c+9]));
414           c += 10;
415           break;
416         case 9:
417           printf(" %02X %02X %02X %02X  %02X %02X %02X %02X  %02X                        %c%c%c%c%c%c%c%c%c\n",
418             data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
419             data[c+8],
420             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]),
421             dcc(data[c+8]));
422           c += 9;
423           break;
424         case 8:
425           printf(" %02X %02X %02X %02X  %02X %02X %02X %02X                            %c%c%c%c%c%c%c%c\n",
426             data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
427             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]));
428           c += 8;
429           break;
430         case 7:
431           printf(" %02X %02X %02X %02X  %02X %02X %02X                               %c%c%c%c%c%c%c\n",
432             data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6],
433             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]));
434           c += 7;
435           break;
436         case 6:
437           printf(" %02X %02X %02X %02X  %02X %02X                                  %c%c%c%c%c%c\n",
438             data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5],
439             dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]));
440           c += 6;
441           break;
442         case 5:
443           printf(" %02X %02X %02X %02X  %02X                                     %c%c%c%c%c\n",
444             data[c], data[c+1], data[c+2], data[c+3], data[c+4],
445             dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]));
446           c += 5;
447           break;
448         case 4:
449           printf(" %02X %02X %02X %02X                                         %c%c%c%c\n",
450             data[c], data[c+1], data[c+2], data[c+3],
451             dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]));
452           c += 4;
453           break;
454         case 3:
455           printf(" %02X %02X %02X                                            %c%c%c\n",
456             data[c], data[c+1], data[c+2],
457             dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]));
458           c += 3;
459           break;
460         case 2:
461           printf(" %02X %02X                                               %c%c\n",
462             data[c], data[c+1],
463             dcc(data[c]), dcc(data[c+1]));
464           c += 2;
465           break;
466         case 1:
467           printf(" %02X                                                  %c\n",
468             data[c],
469             dcc(data[c]));
470           c += 1;
471           break;
472       }
473     }
474   }
475 }
476
477 UCHAR TCP::dcc(UCHAR c)
478 {
479   if (isspace(c)) return ' ';
480   if (isprint(c)) return c;
481   return '.';
482 }