From b34a71e7fc794892f95d01d03914d43ce8ef2b8a Mon Sep 17 00:00:00 2001 From: Chris Tallon Date: Mon, 6 Feb 2006 21:45:43 +0000 Subject: [PATCH] TFTP server (not quite finished) --- Makefile | 4 +- config.c | 6 +- dsock.c | 4 +- mvpserver.c | 17 ++ mvpserver.h | 2 + tftpclient.c | 421 +++++++++++++++++++++++++++++++++++++++++++++++ tftpclient.h | 70 ++++++++ tftpd.c | 89 ++++++++++ tftpd.h | 51 ++++++ thread.c | 14 +- thread.h | 3 +- vomp.conf.sample | 6 + 12 files changed, 676 insertions(+), 11 deletions(-) create mode 100644 tftpclient.c create mode 100644 tftpclient.h create mode 100644 tftpd.c create mode 100644 tftpd.h diff --git a/Makefile b/Makefile index abe6ac2..ff51382 100644 --- a/Makefile +++ b/Makefile @@ -46,9 +46,9 @@ DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"' ### The object files (add further files here): -OBJS = $(PLUGIN).o dsock.o mvpserver.o udpreplier.o bootpd.o mvpclient.o tcp.o \ +OBJS = $(PLUGIN).o dsock.o mvpserver.o udpreplier.o bootpd.o tftpd.o mvpclient.o tcp.o \ remux/ts2ps.o remux/ts2es.o remux/tsremux.o ringbuffer.o \ - recplayer.o config.o log.o thread.o mvpreceiver.o + recplayer.o config.o log.o thread.o mvpreceiver.o tftpclient.o libdvbmpeg/libdvbmpegtools.a: libdvbmpeg/*.c libdvbmpeg/*.cc libdvbmpeg/*.h libdvbmpeg/*.hh diff --git a/config.c b/config.c index dccf524..e4748c1 100644 --- a/config.c +++ b/config.c @@ -113,9 +113,9 @@ int Config::readLine() if (!initted || !file) { log->log("Config", Log::DEBUG, "1"); return 0; } if (!fgets(buffer, BUFFER_LENGTH-1, file)) { log->log("Config", Log::DEBUG, "2"); return 0; } lastLineLength = strlen(buffer); - log->log("Config", Log::DEBUG, "buffer before trim: '%s'", buffer); +// log->log("Config", Log::DEBUG, "buffer before trim: '%s'", buffer); trim(buffer); - log->log("Config", Log::DEBUG, "buffer after trim: '%s'", buffer); +// log->log("Config", Log::DEBUG, "buffer after trim: '%s'", buffer); return 1; } @@ -317,7 +317,7 @@ int Config::findSection(char* section) while(readLine()) { - log->log("Config", Log::DEBUG, "to find '%s' this line '%s'", toFind, buffer); +// log->log("Config", Log::DEBUG, "to find '%s' this line '%s'", toFind, buffer); if (!strcmp(toFind, buffer)) return 1; } return 0; diff --git a/dsock.c b/dsock.c index 80dc532..885d927 100644 --- a/dsock.c +++ b/dsock.c @@ -116,7 +116,7 @@ unsigned char DatagramSocket::waitforMessage(unsigned char how) memset(&buf[mlength], 0, MAXBUFLEN - mlength); strcpy(fromIPA, inet_ntoa(theirAddr.sin_addr)); fromPort = ntohs(theirAddr.sin_port); - log->log("UDP", Log::DEBUG, "%s:%i received length %i", fromIPA, fromPort, mlength); +// log->log("UDP", Log::DEBUG, "%s:%i received length %i", fromIPA, fromPort, mlength); return 2; } @@ -149,7 +149,7 @@ void DatagramSocket::send(char *ipa, short port, char *message, int length) sentLength = sendto(socketnum, message, length, 0, (struct sockaddr *)&theirAddr, addrlen); if (sentLength == length) { - log->log("UDP", Log::DEBUG, "%s:%i sent length %i", ipa, port, length); +// log->log("UDP", Log::DEBUG, "%s:%i sent length %i", ipa, port, length); return; } diff --git a/mvpserver.c b/mvpserver.c index 98ff62f..c1063fa 100644 --- a/mvpserver.c +++ b/mvpserver.c @@ -36,6 +36,7 @@ int MVPServer::stop() udpr.shutdown(); bootpd.shutdown(); + tftpd.shutdown(); log.log("Main", Log::INFO, "Stopped main server thread"); log.shutdown(); @@ -109,6 +110,7 @@ int MVPServer::run() return 0; } + // Start Bootpd if (config.getValueString("General", "Bootp server")) { if (!bootpd.run()) @@ -123,6 +125,21 @@ int MVPServer::run() log.log("Main", Log::INFO, "Not starting Bootpd"); } + // Start Tftpd + if (config.getValueString("General", "TFTP server")) + { + if (!tftpd.run()) + { + log.log("Main", Log::CRIT, "Could not start TFTPd"); + stop(); + return 0; + } + } + else + { + log.log("Main", Log::INFO, "Not starting TFTPd"); + } + // start thread here if (!threadStart()) { diff --git a/mvpserver.h b/mvpserver.h index 06f101a..efb73b5 100644 --- a/mvpserver.h +++ b/mvpserver.h @@ -28,6 +28,7 @@ #include "defines.h" #include "udpreplier.h" #include "bootpd.h" +#include "tftpd.h" #include "mvpclient.h" #include "thread.h" #include "config.h" @@ -48,6 +49,7 @@ class MVPServer : public Thread Config config; UDPReplier udpr; Bootpd bootpd; + Tftpd tftpd; int listeningSocket; }; diff --git a/tftpclient.c b/tftpclient.c new file mode 100644 index 0000000..75d72df --- /dev/null +++ b/tftpclient.c @@ -0,0 +1,421 @@ +/* + Copyright 2006 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "tftpclient.h" + +void dump(unsigned char* data, USHORT size); +unsigned char dcc(UCHAR c); + +TftpClient::TftpClient() +{ + log = Log::getInstance(); + state = 0; + blockNumber = 1; + lastCom = 0; +} + +TftpClient::~TftpClient() +{ + shutdown(); +} + +int TftpClient::shutdown() +{ + if (threadIsActive()) threadCancel(); + ds.shutdown(); + + if (file) + { + fclose(file); + file = NULL; + } + + log->log("TftpClient", Log::DEBUG, "shutdown"); + + return 1; +} + +int TftpClient::run(char* tpeerIP, USHORT tpeerPort, UCHAR* data, int length) +{ + if (threadIsActive()) return 1; + log->log("TftpClient", Log::DEBUG, "Client handler started"); + + strncpy(peerIP, tpeerIP, 16); + peerPort = tpeerPort; + + if (length > 599) return 0; + bufferLength = length; + memcpy(buffer, data, length); + + if (!ds.init(0)) + { + log->log("TftpClient", Log::DEBUG, "DSock init error"); + shutdown(); + return 0; + } + + if (!threadStart()) + { + log->log("TftpClient", Log::DEBUG, "Thread start error"); + shutdown(); + return 0; + } + + return 1; +} + +void TftpClient::threadMethod() +{ + threadDetach(); + + // process the first message received by the parent listener + // the first incoming message is placed in buffer by above run method + if (!processMessage(buffer, bufferLength)) return; + + int retval; + + for(int counter = 0; counter < 10; counter++) + { +// log->log("TftpClient", Log::DEBUG, "Starting wait"); + // timer system to expire after x seconds + retval = ds.waitforMessage(1); +// log->log("TftpClient", Log::DEBUG, "Wait finished"); + + if (retval == 0) + { + log->log("TftpClient", Log::CRIT, "Wait for packet error"); + return; + } + else if (retval == 1) + { + // 1s timer expired + // see if we need to retransmit a data packet + if (((state == 1) || (state == 2)) && (lastCom < (time(NULL) - 3))) + { + log->log("TftpClient", Log::DEBUG, "Retransmitting buffer"); + transmitBuffer(); + } + + continue; + } + else + { + if (strcmp(ds.getFromIPA(), peerIP)) continue; // not from my client's IP + if (ds.getFromPort() != peerPort) continue; // not from my client's port + + if (!processMessage((UCHAR*)ds.getData(), ds.getDataLength())) + { + log->log("TftpClient", Log::INFO, "processMessage terminating connection"); + return; + } + + counter = 0; // that was a valid packet, reset the counter + } + } + log->log("TftpClient", Log::DEBUG, "Lost connection, exiting"); +} + +void TftpClient::threadPostStopCleanup() +{ + log->log("TftpClient", Log::DEBUG, "Deleting tftpclient"); + delete this; // careful +} + +int TftpClient::processMessage(UCHAR* data, int length) +{ +// log->log("TftpClient", Log::DEBUG, "Got request"); +// dump(data, (USHORT)length); + + if ((UINT)length < sizeof(USHORT)) return 0; + USHORT opcode = ntohs(*(USHORT*)data); + data += sizeof(USHORT); + length -= sizeof(USHORT); + + switch(opcode) + { + case 1: // Read request + { + if (!processReadRequest(data, length)) return 0; + break; + } + case 2: // Write request + { + log->log("TftpClient", Log::ERR, "Client wanted to send us a file!"); + return 0; // quit + } + case 3: // Data + { + break; + } + case 4: // Ack + { + if (!processAck(data, length)) return 0; + break; + } + case 5: // Error + { + break; + } + + default: + { + return 0; + } + } + + return 1; +} + +int TftpClient::processReadRequest(UCHAR* data, int length) +{ + if (state != 0) return 0; + + // Safety checking - there should be two nulls in the data/length + + int nullsFound = 0; + for(int i = 0; i < length; i++) + { + if (data[i] == '\0') nullsFound++; + } + + if (nullsFound != 2) return 0; + + char* filename = (char*)data; + char* mode = (char*)(data + strlen(filename) + 1); + + log->log("TftpClient", Log::DEBUG, "RRQ received for %s", filename); + + if (strcasecmp(mode, "octet")) return 0; + if (!openFile(filename)) return 0; + if (!sendBlock()) return 0; + + lastCom = time(NULL); + state = 1; + + return 1; +} + +int TftpClient::processAck(UCHAR* data, int length) +{ + if ((state != 1) && (state != 2)) return 0; + + if (length != 2) return 0; + + USHORT ackBlock = ntohs(*(USHORT*)data); + + if (ackBlock == (blockNumber - 1)) + { + // successful incoming packet + lastCom = time(NULL); + + log->log("TftpClient", Log::DEBUG, "Ack received for block %i - success", ackBlock); + + if (state == 1) // it wasn't the final block + { + sendBlock(); + } + else + { + // state == 2, end of transfer. kill connection + log->log("TftpClient", Log::INFO, "File transfer finished"); + return 0; + } + } + else + { + log->log("TftpClient", Log::DEBUG, "Ack received for block %i - rejected\n", ackBlock); + } + + return 1; +} + +int TftpClient::openFile(char* filename) +{ + file = fopen("/opt/dvb/vomp-dongle-0.1.1", "r"); + if (!file) return 0; + return 1; +} + +int TftpClient::sendBlock() +{ + *(USHORT*)&buffer[0] = htons(3); + *(USHORT*)&buffer[2] = htons(blockNumber++); + bufferLength = 4 + fread(&buffer[4], 1, 512, file); + + if (bufferLength < 516) // 512 + 4 header + { + // end of file + state = 2; + fclose(file); + file = NULL; + } + else + { + state = 1; + } + + transmitBuffer(); + + return 1; +} + +void TftpClient::transmitBuffer() +{ + ds.send(peerIP, peerPort, (char*)buffer, bufferLength); +// dump(buffer, bufferLength); + log->log("TftpClient", Log::DEBUG, "Sent block number %i", blockNumber - 1); +} + +void dump(unsigned char* data, USHORT size) +{ + printf("Size = %u\n", size); + + USHORT c = 0; + while(c < size) + { + if ((size - c) > 15) + { + 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", + data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7], + data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15], + 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]), + 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])); + c += 16; + } + else + { + switch (size - c) + { + case 15: + 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", + data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7], + data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], + 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]), + 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])); + c += 15; + break; + case 14: + 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", + data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7], + data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], + 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]), + dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13])); + c += 14; + break; + case 13: + 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", + data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7], + data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], + 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]), + dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12])); + c += 13; + break; + case 12: + 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", + data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7], + data[c+8], data[c+9], data[c+10], data[c+11], + 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]), + dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11])); + c += 12; + break; + case 11: + printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c\n", + data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7], + data[c+8], data[c+9], data[c+10], + 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]), + dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10])); + c += 11; + break; + case 10: + printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c\n", + data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7], + data[c+8], data[c+9], + 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]), + dcc(data[c+8]), dcc(data[c+9])); + c += 10; + break; + case 9: + printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c\n", + data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7], + data[c+8], + 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]), + dcc(data[c+8])); + c += 9; + break; + case 8: + printf(" %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c\n", + data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7], + 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])); + c += 8; + break; + case 7: + printf(" %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c\n", + data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], + 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])); + c += 7; + break; + case 6: + printf(" %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c\n", + data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], + dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5])); + c += 6; + break; + case 5: + printf(" %02X %02X %02X %02X %02X %c%c%c%c%c\n", + data[c], data[c+1], data[c+2], data[c+3], data[c+4], + dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4])); + c += 5; + break; + case 4: + printf(" %02X %02X %02X %02X %c%c%c%c\n", + data[c], data[c+1], data[c+2], data[c+3], + dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3])); + c += 4; + break; + case 3: + printf(" %02X %02X %02X %c%c%c\n", + data[c], data[c+1], data[c+2], + dcc(data[c]), dcc(data[c+1]), dcc(data[c+2])); + c += 3; + break; + case 2: + printf(" %02X %02X %c%c\n", + data[c], data[c+1], + dcc(data[c]), dcc(data[c+1])); + c += 2; + break; + case 1: + printf(" %02X %c\n", + data[c], + dcc(data[c])); + c += 1; + break; + } + } + } +} + +unsigned char dcc(UCHAR c) +{ + if (isspace(c)) return ' '; + if (isprint(c)) return c; + return '.'; +} + diff --git a/tftpclient.h b/tftpclient.h new file mode 100644 index 0000000..2a1bdc6 --- /dev/null +++ b/tftpclient.h @@ -0,0 +1,70 @@ +/* + Copyright 2006 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef TFTPCLIENT_H +#define TFTPCLIENT_H + +#include +#include +#include +#include + +#include "defines.h" +#include "log.h" +#include "dsock.h" +#include "thread.h" + +class TftpClient : public Thread +{ + public: + TftpClient(); + virtual ~TftpClient(); + + int run(char* ip, USHORT port, UCHAR* data, int length); + int shutdown(); + + private: + Log* log; + DatagramSocket ds; + char peerIP[17]; + USHORT peerPort; + UCHAR buffer[600]; + int bufferLength; + time_t lastCom; + FILE* file; + int state; + // 0 = start + // 1 = awaiting ack + // 2 = transfer finished, awaiting last ack + USHORT blockNumber; + + void threadMethod(); + void threadPostStopCleanup(); + + int processMessage(UCHAR* data, int length); + int processReadRequest(UCHAR* data, int length); + int processAck(UCHAR* data, int length); + + int openFile(char* filename); + int sendBlock(); + void transmitBuffer(); +}; + +#endif diff --git a/tftpd.c b/tftpd.c new file mode 100644 index 0000000..564b2c5 --- /dev/null +++ b/tftpd.c @@ -0,0 +1,89 @@ +/* + Copyright 2006 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "tftpd.h" + +Tftpd::Tftpd() +{ + log = Log::getInstance(); +} + +Tftpd::~Tftpd() +{ + shutdown(); +} + +int Tftpd::shutdown() +{ + if (threadIsActive()) threadCancel(); + ds.shutdown(); + + return 1; +} + +int Tftpd::run() +{ + if (threadIsActive()) return 1; + log->log("Tftpd", Log::DEBUG, "Starting Tftpd"); + + if (!ds.init(16869)) + { + log->log("Tftpd", Log::DEBUG, "DSock init error"); + shutdown(); + return 0; + } + + if (!threadStart()) + { + log->log("Tftpd", Log::DEBUG, "Thread start error"); + shutdown(); + return 0; + } + + log->log("Tftpd", Log::DEBUG, "Bootp replier started"); + return 1; +} + +void Tftpd::threadMethod() +{ + int retval; + while(1) + { + log->log("Tftpd", Log::DEBUG, "Starting wait"); + retval = ds.waitforMessage(0); + log->log("Tftpd", Log::DEBUG, "Wait finished"); + + if (retval == 0) + { + log->log("Tftpd", Log::CRIT, "Wait for packet error"); + return; + } + else if (retval == 1) + { + continue; + } + else + { + TftpClient* t = new TftpClient(); + t->run(ds.getFromIPA(), ds.getFromPort(), (UCHAR*)ds.getData(), ds.getDataLength()); + } + } +} + diff --git a/tftpd.h b/tftpd.h new file mode 100644 index 0000000..f866feb --- /dev/null +++ b/tftpd.h @@ -0,0 +1,51 @@ +/* + Copyright 2006 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef TFTPD_H +#define TFTPD_H + +#include +#include +#include +#include + +#include "defines.h" +#include "log.h" +#include "dsock.h" +#include "thread.h" +#include "tftpclient.h" + +class Tftpd : public Thread +{ + public: + Tftpd(); + virtual ~Tftpd(); + + int run(); + int shutdown(); + + private: + void threadMethod(); + + DatagramSocket ds; + Log* log; +}; + +#endif diff --git a/thread.c b/thread.c index fe5490a..0eadacb 100755 --- a/thread.c +++ b/thread.c @@ -24,9 +24,9 @@ void threadInternalStart(void *arg) { // I don't want signals - sigset_t sigset; - sigfillset(&sigset); - pthread_sigmask(SIG_BLOCK, &sigset, NULL); + sigset_t sigs; + sigfillset(&sigs); + pthread_sigmask(SIG_BLOCK, &sigs, NULL); Thread *t = (Thread *)arg; t->threadInternalStart2(); @@ -35,6 +35,7 @@ void threadInternalStart(void *arg) void Thread::threadInternalStart2() { threadMethod(); + this->threadPostStopCleanup(); } Thread::Thread() @@ -58,6 +59,7 @@ void Thread::threadStop() // Signal thread here in case it's waiting threadSignal(); pthread_join(pthread, NULL); + this->threadPostStopCleanup(); } void Thread::threadCancel() @@ -65,6 +67,7 @@ void Thread::threadCancel() threadActive = 0; pthread_cancel(pthread); pthread_join(pthread, NULL); + this->threadPostStopCleanup(); } void Thread::threadCheckExit() @@ -95,3 +98,8 @@ void Thread::threadWaitForSignal() pthread_cond_wait(&threadCond, &threadCondMutex); pthread_mutex_unlock(&threadCondMutex); } + +void Thread::threadDetach() +{ + pthread_detach(pthread); +} diff --git a/thread.h b/thread.h index bef94be..c48ea97 100755 --- a/thread.h +++ b/thread.h @@ -27,9 +27,9 @@ class Thread { protected: - // Override this method in derived classes virtual void threadMethod()=0; + virtual void threadPostStopCleanup() {}; // Methods to use from outside the thread int threadStart(); // start the thread. threadMethod() will be called in derived class @@ -42,6 +42,7 @@ class Thread // Methods to use from inside the thread void threadCheckExit(); // terminates thread if threadStop() has been called void threadWaitForSignal(); // pauses thread until threadSignal() is called + void threadDetach(); // Detaches the thread // Internal bits and pieces diff --git a/vomp.conf.sample b/vomp.conf.sample index 2cc51cc..c52e473 100644 --- a/vomp.conf.sample +++ b/vomp.conf.sample @@ -16,3 +16,9 @@ ## name and server # Bootp server = 1 + +## Enable this to start the built in TFTP server +## Required to boot the MVP if you have not got a +## TFTP server running elsewhere + +# TFTP server = 1 -- 2.39.5