2 Copyright 2006 Chris Tallon
4 This file is part of VOMP.
6 VOMP is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 VOMP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with VOMP; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "tftpclient.h"
23 void dump(unsigned char* data, USHORT size);
24 unsigned char dcc(UCHAR c);
26 TftpClient::TftpClient()
28 log = Log::getInstance();
34 TftpClient::~TftpClient()
39 int TftpClient::shutdown()
41 if (threadIsActive()) threadCancel();
50 log->log("TftpClient", Log::DEBUG, "shutdown");
55 int TftpClient::run(char* tpeerIP, USHORT tpeerPort, UCHAR* data, int length)
57 if (threadIsActive()) return 1;
58 log->log("TftpClient", Log::DEBUG, "Client handler started");
60 strncpy(peerIP, tpeerIP, 16);
63 if (length > 599) return 0;
64 bufferLength = length;
65 memcpy(buffer, data, length);
69 log->log("TftpClient", Log::DEBUG, "DSock init error");
76 log->log("TftpClient", Log::DEBUG, "Thread start error");
84 void TftpClient::threadMethod()
88 // process the first message received by the parent listener
89 // the first incoming message is placed in buffer by above run method
90 if (!processMessage(buffer, bufferLength)) return;
94 for(int counter = 0; counter < 10; counter++)
96 // log->log("TftpClient", Log::DEBUG, "Starting wait");
97 // timer system to expire after x seconds
98 retval = ds.waitforMessage(1);
99 // log->log("TftpClient", Log::DEBUG, "Wait finished");
103 log->log("TftpClient", Log::CRIT, "Wait for packet error");
106 else if (retval == 1)
109 // see if we need to retransmit a data packet
110 if (((state == 1) || (state == 2)) && (lastCom < (time(NULL) - 3)))
112 log->log("TftpClient", Log::DEBUG, "Retransmitting buffer");
120 if (strcmp(ds.getFromIPA(), peerIP)) continue; // not from my client's IP
121 if (ds.getFromPort() != peerPort) continue; // not from my client's port
123 if (!processMessage((UCHAR*)ds.getData(), ds.getDataLength()))
125 log->log("TftpClient", Log::INFO, "processMessage terminating connection");
129 counter = 0; // that was a valid packet, reset the counter
132 log->log("TftpClient", Log::DEBUG, "Lost connection, exiting");
135 void TftpClient::threadPostStopCleanup()
137 log->log("TftpClient", Log::DEBUG, "Deleting tftpclient");
138 delete this; // careful
141 int TftpClient::processMessage(UCHAR* data, int length)
143 // log->log("TftpClient", Log::DEBUG, "Got request");
144 // dump(data, (USHORT)length);
146 if ((UINT)length < sizeof(USHORT)) return 0;
147 USHORT opcode = ntohs(*(USHORT*)data);
148 data += sizeof(USHORT);
149 length -= sizeof(USHORT);
153 case 1: // Read request
155 if (!processReadRequest(data, length)) return 0;
158 case 2: // Write request
160 log->log("TftpClient", Log::ERR, "Client wanted to send us a file!");
169 if (!processAck(data, length)) return 0;
186 int TftpClient::processReadRequest(UCHAR* data, int length)
188 if (state != 0) return 0;
190 // Safety checking - there should be two nulls in the data/length
193 for(int i = 0; i < length; i++)
195 if (data[i] == '\0') nullsFound++;
198 if (nullsFound != 2) return 0;
200 char* filename = (char*)data;
201 char* mode = (char*)(data + strlen(filename) + 1);
203 log->log("TftpClient", Log::DEBUG, "RRQ received for %s", filename);
205 if (strcasecmp(mode, "octet")) return 0;
206 if (!openFile(filename)) return 0;
207 if (!sendBlock()) return 0;
209 lastCom = time(NULL);
215 int TftpClient::processAck(UCHAR* data, int length)
217 if ((state != 1) && (state != 2)) return 0;
219 if (length != 2) return 0;
221 USHORT ackBlock = ntohs(*(USHORT*)data);
223 if (ackBlock == (blockNumber - 1))
225 // successful incoming packet
226 lastCom = time(NULL);
228 log->log("TftpClient", Log::DEBUG, "Ack received for block %i - success", ackBlock);
230 if (state == 1) // it wasn't the final block
236 // state == 2, end of transfer. kill connection
237 log->log("TftpClient", Log::INFO, "File transfer finished");
243 log->log("TftpClient", Log::DEBUG, "Ack received for block %i - rejected\n", ackBlock);
249 int TftpClient::openFile(char* filename)
251 file = fopen("/opt/dvb/vomp-dongle-0.1.1", "r");
256 int TftpClient::sendBlock()
258 *(USHORT*)&buffer[0] = htons(3);
259 *(USHORT*)&buffer[2] = htons(blockNumber++);
260 bufferLength = 4 + fread(&buffer[4], 1, 512, file);
262 if (bufferLength < 516) // 512 + 4 header
279 void TftpClient::transmitBuffer()
281 ds.send(peerIP, peerPort, (char*)buffer, bufferLength);
282 // dump(buffer, bufferLength);
283 log->log("TftpClient", Log::DEBUG, "Sent block number %i", blockNumber - 1);
286 void dump(unsigned char* data, USHORT size)
288 printf("Size = %u\n", size);
295 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",
296 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
297 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15],
298 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]),
299 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]));
307 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",
308 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
309 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14],
310 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]),
311 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]));
315 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",
316 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
317 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13],
318 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]),
319 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]));
323 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",
324 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
325 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12],
326 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]),
327 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]));
331 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",
332 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
333 data[c+8], data[c+9], data[c+10], data[c+11],
334 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]),
335 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]));
339 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %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],
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]));
347 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c\n",
348 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
349 data[c+8], data[c+9],
350 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]),
351 dcc(data[c+8]), dcc(data[c+9]));
355 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c\n",
356 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
358 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 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c\n",
364 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
365 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]));
369 printf(" %02X %02X %02X %02X %02X %02X %02X %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],
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]));
375 printf(" %02X %02X %02X %02X %02X %02X %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],
377 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]));
381 printf(" %02X %02X %02X %02X %02X %c%c%c%c%c\n",
382 data[c], data[c+1], data[c+2], data[c+3], data[c+4],
383 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]));
387 printf(" %02X %02X %02X %02X %c%c%c%c\n",
388 data[c], data[c+1], data[c+2], data[c+3],
389 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]));
393 printf(" %02X %02X %02X %c%c%c\n",
394 data[c], data[c+1], data[c+2],
395 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]));
399 printf(" %02X %02X %c%c\n",
401 dcc(data[c]), dcc(data[c+1]));
415 unsigned char dcc(UCHAR c)
417 if (isspace(c)) return ' ';
418 if (isprint(c)) return c;