]> git.vomp.tv Git - vompclient.git/blob - tcp.cc
Send MAC in login packet, volume read from hw at startup
[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
24 TCP::TCP()
25 {
26   sock = 0;
27   connected = 0;
28   timeoutEnabled = 1;
29 }
30
31 TCP::~TCP()
32 {
33   if (connected)
34   {
35     close(sock);
36     Log::getInstance()->log("TCP", Log::DEBUG, "Have closed");
37   }
38 }
39
40 void TCP::disableTimeout()
41 {
42   timeoutEnabled = 0;
43 }
44
45 void TCP::getMAC(char* dest)
46 {
47   struct ifreq ifr;
48   strcpy(ifr.ifr_name, "eth0");
49   ioctl(sock, SIOCGIFHWADDR, &ifr);
50   memcpy(dest, ifr.ifr_hwaddr.sa_data, 6);
51 }
52
53 int TCP::connectTo(char* host, unsigned short port)
54 {
55   sock = socket(PF_INET, SOCK_STREAM, 0);
56   if (sock == -1) return 0;
57
58   struct sockaddr_in dest_addr;
59   dest_addr.sin_family = AF_INET;
60   dest_addr.sin_port = htons(port);
61
62   if (!inet_aton(host, &dest_addr.sin_addr))
63   {
64     close(sock);
65     return 0;
66   }
67
68   memset(&(dest_addr.sin_zero), '\0', 8);
69
70   // set non blocking
71   int oldflags = fcntl (sock, F_GETFL, 0);
72   oldflags |= O_NONBLOCK;
73   fcntl(sock, F_SETFL, oldflags);
74
75   // Set receive window
76   size_t rxBufferSize = 2048;
77   setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &rxBufferSize, sizeof(size_t));
78
79   // ok, how to open a connection in non blocking mode (and therefore have a self set timeout!!)
80
81   int success = connect(sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr));
82
83   if (success == 0)  // if by some miracle the connection succeeded in no time flat, just return!
84   {
85     connected = 1;
86     return 1;
87   }
88
89   // first check errno for EINPROGRESS, otherwise it's a fail
90   // this doesn't work?
91   if (errno != EINPROGRESS)
92   {
93     close(sock);
94     return 0;
95   }
96
97   // now do a timeout wait on writability on the socket
98
99   fd_set connectSet;
100   struct timeval timeout;
101   FD_ZERO(&connectSet);
102   FD_SET(sock, &connectSet);
103   timeout.tv_sec = 10;
104   timeout.tv_usec = 0;
105   success = select(sock + 1, NULL, &connectSet, NULL, &timeout);
106   if (success < 1)
107   {
108     // timeout or error
109     close(sock);
110     return 0;
111   }
112
113   // so the socket became available for writing. Contrary to expectation, this doesn't actually
114   // mean it connected...
115
116   int soError;
117   socklen_t soErrorSize = sizeof(soError);
118   int gso = getsockopt(sock, SOL_SOCKET, SO_ERROR, &soError, &soErrorSize);
119
120   if ((gso == 0) && (soError == 0))
121   {
122     // success!
123     connected = 1;
124     return 1;
125   }
126   else
127   {
128     close(sock);
129     return 0;
130   }
131
132 /*
133 The full documentation:
134
135        EINPROGRESS
136               The  socket is non-blocking and the connection canĀ­
137               not be completed immediately.  It  is  possible  to
138               select(2)  or  poll(2)  for completion by selecting
139               the socket  for  writing.  After  select  indicates
140               writability, use getsockopt(2) to read the SO_ERROR
141               option at level  SOL_SOCKET  to  determine  whether
142               connect  completed  successfully (SO_ERROR is zero)
143               or unsuccessfully (SO_ERROR is  one  of  the  usual
144               error  codes listed here, explaining the reason for
145               the failure).
146 */
147 }
148
149 void TCP::assignSocket(int tsocket)
150 {
151   sock = tsocket;
152 }
153
154 int TCP::isConnected()
155 {
156   return connected;
157 }
158
159 int TCP::sendPacket(void* bufR, size_t count)
160 {
161   size_t bytes_sent = 0;
162   int this_write;
163   int temp_write;
164
165   unsigned char* buf = (unsigned char*)bufR;
166
167   while (bytes_sent < count)
168   {
169     do
170     {
171       temp_write = this_write = write(sock, buf, count - bytes_sent);
172 //      Log::getInstance()->log("TCP", Log::DEBUG, "TCP has written %i bytes", temp_write);
173     } while ( (this_write < 0) && (errno == EINTR) );
174
175
176     if (this_write <= 0)
177     {
178       return(this_write);
179     }
180     bytes_sent += this_write;
181     buf += this_write;
182   }
183   return(count);
184 }
185
186 UCHAR* TCP::receivePacket()
187 {
188   ULONG packetLength;
189   int success;
190
191   success = readData((UCHAR*)&packetLength, sizeof(int));
192   if (!success) return NULL;
193
194   packetLength = ntohl(packetLength);
195
196   if (packetLength > 500000)
197   {
198     Log::getInstance()->log("TCP", Log::ERR, "Received packet > 500000");
199     return NULL;
200   }
201   if (packetLength == 0)
202   {
203     Log::getInstance()->log("TCP", Log::ERR, "Received packet len = 0");
204     return NULL;
205   }
206
207   UCHAR* buffer = (UCHAR*) malloc(packetLength);
208
209   success = readData(buffer, packetLength);
210
211   if (!success)
212   {
213     Log::getInstance()->log("TCP", Log::ERR, "readData failed");
214     free(buffer);
215     close(sock);
216     connected = 0;
217     return NULL;
218   }
219
220   dataLength = packetLength;
221   return buffer;
222 }
223
224 int TCP::getDataLength()
225 {
226   return dataLength;
227 }
228
229 int TCP::readData(UCHAR* buffer, int totalBytes)
230 {
231
232   int bytesRead = 0;
233   int thisRead;
234   int readTries = 0;
235   int success;
236   fd_set readSet;
237   struct timeval timeout;
238   struct timeval* passToSelect;
239
240   if (timeoutEnabled) passToSelect = &timeout;
241   else passToSelect = NULL;
242
243   while(1)
244   {
245     FD_ZERO(&readSet);
246     FD_SET(sock, &readSet);
247     timeout.tv_sec = 10;
248     timeout.tv_usec = 0;
249     success = select(sock + 1, &readSet, NULL, NULL, passToSelect);
250     if (success < 1)
251     {
252       Log::getInstance()->log("TCP", Log::ERR, "Error or timeout");
253       return 0;  // error, or timeout
254     }
255
256     thisRead = read(sock, &buffer[bytesRead], totalBytes - bytesRead);
257 //    printf("read %i\n", thisRead);
258     if (!thisRead)
259     {
260       // if read returns 0 then connection is closed
261       // in non-blocking mode if read is called with no data available, it returns -1
262       // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
263       Log::getInstance()->log("TCP", Log::ERR, "Detected connection closed");
264       connected = 0;
265       return 0;
266     }
267     bytesRead += thisRead;
268
269     if (bytesRead == totalBytes)
270     {
271       return 1;
272     }
273     else
274     {
275       if (++readTries == 100)
276       {
277 //        Log::getInstance()->log("TCP", Log::ERR, "Too many reads");
278 //        return 0;
279       }
280     }
281   }
282 }
283
284 void TCP::dump(unsigned char* data, ULONG size)
285 {
286   printf("Size = %lu\n", size);
287
288   ULONG c = 0;
289   while(c < size)
290   {
291     if ((size - c) > 15)
292     {
293       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",
294         data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
295         data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15],
296         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]),
297         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]));
298       c += 16;
299     }
300     else
301     {
302       switch (size - c)
303       {
304         case 15:
305           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",
306             data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
307             data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14],
308             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]),
309             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]));
310           c += 15;
311           break;
312         case 14:
313           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",
314             data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
315             data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13],
316             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]),
317             dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]));
318           c += 14;
319           break;
320         case 13:
321           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",
322             data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
323             data[c+8], data[c+9], data[c+10], data[c+11], data[c+12],
324             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]),
325             dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]));
326           c += 13;
327           break;
328         case 12:
329           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",
330             data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
331             data[c+8], data[c+9], data[c+10], data[c+11],
332             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]),
333             dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]));
334           c += 12;
335           break;
336         case 11:
337           printf(" %02X %02X %02X %02X  %02X %02X %02X %02X  %02X %02X %02X                  %c%c%c%c%c%c%c%c%c%c%c\n",
338             data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
339             data[c+8], data[c+9], data[c+10],
340             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]),
341             dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]));
342           c += 11;
343           break;
344         case 10:
345           printf(" %02X %02X %02X %02X  %02X %02X %02X %02X  %02X %02X                     %c%c%c%c%c%c%c%c%c%c\n",
346             data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
347             data[c+8], data[c+9],
348             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]),
349             dcc(data[c+8]), dcc(data[c+9]));
350           c += 10;
351           break;
352         case 9:
353           printf(" %02X %02X %02X %02X  %02X %02X %02X %02X  %02X                        %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],
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]));
358           c += 9;
359           break;
360         case 8:
361           printf(" %02X %02X %02X %02X  %02X %02X %02X %02X                            %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             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           c += 8;
365           break;
366         case 7:
367           printf(" %02X %02X %02X %02X  %02X %02X %02X                               %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],
369             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]));
370           c += 7;
371           break;
372         case 6:
373           printf(" %02X %02X %02X %02X  %02X %02X                                  %c%c%c%c%c%c\n",
374             data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5],
375             dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]));
376           c += 6;
377           break;
378         case 5:
379           printf(" %02X %02X %02X %02X  %02X                                     %c%c%c%c%c\n",
380             data[c], data[c+1], data[c+2], data[c+3], data[c+4],
381             dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]));
382           c += 5;
383           break;
384         case 4:
385           printf(" %02X %02X %02X %02X                                         %c%c%c%c\n",
386             data[c], data[c+1], data[c+2], data[c+3],
387             dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]));
388           c += 4;
389           break;
390         case 3:
391           printf(" %02X %02X %02X                                            %c%c%c\n",
392             data[c], data[c+1], data[c+2],
393             dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]));
394           c += 3;
395           break;
396         case 2:
397           printf(" %02X %02X                                               %c%c\n",
398             data[c], data[c+1],
399             dcc(data[c]), dcc(data[c+1]));
400           c += 2;
401           break;
402         case 1:
403           printf(" %02X                                                  %c\n",
404             data[c],
405             dcc(data[c]));
406           c += 1;
407           break;
408       }
409     }
410   }
411 }
412
413 UCHAR TCP::dcc(UCHAR c)
414 {
415   if (isspace(c)) return ' ';
416   if (isprint(c)) return c;
417   return '.';
418 }