]> git.vomp.tv Git - vompserver.git/commitdiff
Finished Bootp/TFTP server
authorChris Tallon <chris@vomp.tv>
Sat, 18 Feb 2006 18:47:06 +0000 (18:47 +0000)
committerChris Tallon <chris@vomp.tv>
Sat, 18 Feb 2006 18:47:06 +0000 (18:47 +0000)
bootpd.c
mvpserver.c
tftpclient.c
tftpclient.h
tftpd.c
tftpd.h
thread.c
vomp-00-00-00-00-00-00.conf.sample
vomp.conf.sample

index 1786d5e50d0c883340adf02be3a7d1bc7e1e3c43..0a98fe0fb300252e25e51f089f38c2d118d448f9 100644 (file)
--- a/bootpd.c
+++ b/bootpd.c
@@ -222,7 +222,17 @@ void Bootpd::processRequest(UCHAR* data, int length)
   }
 
   // Set filename
-  strncpy((char*)&data[108], "/mvp/vomp-dongle", 127);
+  char* tftpFileName = config.getValueString("Boot", "TFTP file name");
+  if (tftpFileName)
+  {
+    strncpy((char*)&data[108], tftpFileName, 127);
+    delete[] tftpFileName;
+  }
+  else
+  {
+    data[108] = '-';
+    data[109] = '\0';
+  }
 
   // set to reply
   data[0] = 2;
index c1063faa2cd02f8d7d5ba8aeebfd5181f562f636..438405c67aaca06fd22d0eb5e6b2cfb795003e3a 100644 (file)
@@ -110,8 +110,22 @@ int MVPServer::run()
     return 0;
   }
 
-  // Start Bootpd
-  if (config.getValueString("General", "Bootp server"))
+  // Read config and start bootp and tftp as appropriate
+
+  char* configString;
+  int bootpEnabled = 0;
+  int tftpEnabled = 0;
+
+  configString = config.getValueString("General", "Bootp server enabled");
+  if (configString && (!strcasecmp(configString, "yes"))) bootpEnabled = 1;
+  if (configString) delete[] configString;
+
+  configString = config.getValueString("General", "TFTP server enabled");
+  if (configString && (!strcasecmp(configString, "yes"))) tftpEnabled = 1;
+  if (configString) delete[] configString;
+
+
+  if (bootpEnabled)
   {
     if (!bootpd.run())
     {
@@ -125,10 +139,38 @@ int MVPServer::run()
     log.log("Main", Log::INFO, "Not starting Bootpd");
   }
 
-  // Start Tftpd
-  if (config.getValueString("General", "TFTP server"))
+  if (tftpEnabled)
   {
-    if (!tftpd.run())
+    char tftpPath[PATH_MAX];
+//    snprintf(configFileName, PATH_MAX, "%s/vomp.conf", configDir);
+
+    configString = config.getValueString("General", "TFTP directory");
+    if (configString)
+    {
+      snprintf(tftpPath, PATH_MAX, "%s", configString);
+
+      // this will never happen.. surely.
+      if ((strlen(tftpPath) + 2) >= PATH_MAX)
+      {
+        delete[] configString;
+        log.log("Main", Log::CRIT, "Could not understand TFTP directory from config");
+        stop();
+        return 0;
+      }
+
+      // if there isn't a / at the end of the dir, add one
+      if (tftpPath[strlen(tftpPath) - 1] != '/') strcat(tftpPath, "/");
+
+      delete[] configString;
+    }
+    else
+    {
+      snprintf(tftpPath, PATH_MAX, "%s/", configDir);
+    }
+
+    log.log("Main", Log::INFO, "TFTP path '%s'", tftpPath);
+
+    if (!tftpd.run(tftpPath))
     {
       log.log("Main", Log::CRIT, "Could not start TFTPd");
       stop();
@@ -140,6 +182,7 @@ int MVPServer::run()
     log.log("Main", Log::INFO, "Not starting TFTPd");
   }
 
+
   // start thread here
   if (!threadStart())
   {
index 75d72dfeddacf7d3c66447037191cf084701c2c6..8613339c0bbae48d2922a70d5f13931fdbdaf4f0 100644 (file)
@@ -20,9 +20,6 @@
 
 #include "tftpclient.h"
 
-void dump(unsigned char* data, USHORT size);
-unsigned char dcc(UCHAR c);
-
 TftpClient::TftpClient()
 {
   log = Log::getInstance();
@@ -33,6 +30,7 @@ TftpClient::TftpClient()
 
 TftpClient::~TftpClient()
 {
+  log->log("TftpClient", Log::DEBUG, "Someone calls tftpclient::~tftpclient");
   shutdown();
 }
 
@@ -52,11 +50,13 @@ int TftpClient::shutdown()
   return 1;
 }
 
-int TftpClient::run(char* tpeerIP, USHORT tpeerPort, UCHAR* data, int length)
+int TftpClient::run(char* tbaseDir, char* tpeerIP, USHORT tpeerPort, UCHAR* data, int length)
 {
   if (threadIsActive()) return 1;
   log->log("TftpClient", Log::DEBUG, "Client handler started");
 
+  baseDir = tbaseDir;
+
   strncpy(peerIP, tpeerIP, 16);
   peerPort = tpeerPort;
 
@@ -87,7 +87,11 @@ void TftpClient::threadMethod()
 
   // 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;
+  if (!processMessage(buffer, bufferLength))
+  {
+    log->log("TftpClient", Log::INFO, "threadMethod terminating connection");
+    return;
+  }
 
   int retval;
 
@@ -107,9 +111,9 @@ void TftpClient::threadMethod()
     {
       // 1s timer expired
       // see if we need to retransmit a data packet
-      if (((state == 1) || (state == 2)) && (lastCom < (time(NULL) - 3)))
+      if (((state == 1) || (state == 2)) && (lastCom < (time(NULL) - 1)))
       {
-        log->log("TftpClient", Log::DEBUG, "Retransmitting buffer");
+//        log->log("TftpClient", Log::DEBUG, "Retransmitting buffer");
         transmitBuffer();
       }
 
@@ -134,8 +138,8 @@ void TftpClient::threadMethod()
 
 void TftpClient::threadPostStopCleanup()
 {
-  log->log("TftpClient", Log::DEBUG, "Deleting tftpclient");
-  delete this; // careful
+//  log->log("TftpClient", Log::DEBUG, "Deleting tftpclient");
+//  delete this; // careful
 }
 
 int TftpClient::processMessage(UCHAR* data, int length)
@@ -162,7 +166,8 @@ int TftpClient::processMessage(UCHAR* data, int length)
     }
     case 3: // Data
     {
-      break;
+      log->log("TftpClient", Log::ERR, "Client sent a data packet!");
+      return 0; // quit
     }
     case 4: // Ack
     {
@@ -176,6 +181,7 @@ int TftpClient::processMessage(UCHAR* data, int length)
 
     default:
     {
+      log->log("TftpClient", Log::ERR, "Client TFTP protocol error");
       return 0;
     }
   }
@@ -225,7 +231,7 @@ int TftpClient::processAck(UCHAR* data, int length)
     // successful incoming packet
     lastCom = time(NULL);
 
-    log->log("TftpClient", Log::DEBUG, "Ack received for block %i - success", ackBlock);
+//    log->log("TftpClient", Log::DEBUG, "Ack received for block %i - success", ackBlock);
 
     if (state == 1) // it wasn't the final block
     {
@@ -240,15 +246,34 @@ int TftpClient::processAck(UCHAR* data, int length)
   }
   else
   {
-    log->log("TftpClient", Log::DEBUG, "Ack received for block %i - rejected\n", ackBlock);
+//    log->log("TftpClient", Log::DEBUG, "Ack received for block %i - rejected, retransmitting block\n", ackBlock);
+    transmitBuffer();
   }
 
   return 1;
 }
 
-int TftpClient::openFile(char* filename)
+int TftpClient::openFile(char* requestedFile)
 {
-  file = fopen("/opt/dvb/vomp-dongle-0.1.1", "r");
+  char fileName[PATH_MAX];
+  strcpy(fileName, requestedFile);
+
+  for(UINT i = 0; i < strlen(fileName); i++)
+  {
+    if (fileName[i] == '/')
+    {
+      log->log("TftpClient", Log::ERR, "TFTP filename from client contained a path");
+      return 0;
+    }
+  }
+
+  char fileName2[PATH_MAX];
+  snprintf(fileName2, PATH_MAX, "%s%s", baseDir, fileName);
+
+  log->log("TftpClient", Log::INFO, "File: '%s'", fileName2);
+
+
+  file = fopen(fileName2, "r");
   if (!file) return 0;
   return 1;
 }
@@ -280,142 +305,5 @@ void TftpClient::transmitBuffer()
 {
   ds.send(peerIP, peerPort, (char*)buffer, bufferLength);
 //  dump(buffer, bufferLength);
-  log->log("TftpClient", Log::DEBUG, "Sent block number %i", blockNumber - 1);
+//  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 '.';
-}
-
index 2a1bdc6ce3eaf7faad8d32058fb369e10053e5dd..5a80c2c8d881185b4510f1231b569c38c1ac2ddd 100644 (file)
@@ -37,12 +37,13 @@ class TftpClient : public Thread
     TftpClient();
     virtual ~TftpClient();
 
-    int run(char* ip, USHORT port, UCHAR* data, int length);
+    int run(char* baseDir, char* ip, USHORT port, UCHAR* data, int length);
     int shutdown();
 
   private:
     Log* log;
     DatagramSocket ds;
+    char* baseDir;
     char peerIP[17];
     USHORT peerPort;
     UCHAR buffer[600];
diff --git a/tftpd.c b/tftpd.c
index 564b2c5a693385eb3ed287aea4cc22551d747775..38415e03fb94672cca5f414d5adc0bcf83ffcece 100644 (file)
--- a/tftpd.c
+++ b/tftpd.c
@@ -23,6 +23,7 @@
 Tftpd::Tftpd()
 {
   log = Log::getInstance();
+  baseDir = NULL;
 }
 
 Tftpd::~Tftpd()
@@ -35,13 +36,16 @@ int Tftpd::shutdown()
   if (threadIsActive()) threadCancel();
   ds.shutdown();
 
+  if (baseDir) delete[] baseDir;
+  baseDir = NULL;
+
   return 1;
 }
 
-int Tftpd::run()
+int Tftpd::run(char* tbaseDir)
 {
   if (threadIsActive()) return 1;
-  log->log("Tftpd", Log::DEBUG, "Starting Tftpd");
+  log->log("Tftpd", Log::DEBUG, "Starting TFTPd");
 
   if (!ds.init(16869))
   {
@@ -50,6 +54,9 @@ int Tftpd::run()
     return 0;
   }
 
+  baseDir = new char[strlen(tbaseDir) + 1];
+  strcpy(baseDir, tbaseDir);
+
   if (!threadStart())
   {
     log->log("Tftpd", Log::DEBUG, "Thread start error");
@@ -57,7 +64,7 @@ int Tftpd::run()
     return 0;
   }
 
-  log->log("Tftpd", Log::DEBUG, "Bootp replier started");
+  log->log("Tftpd", Log::DEBUG, "TFTP server started with base path '%s'", baseDir);
   return 1;
 }
 
@@ -82,7 +89,7 @@ void Tftpd::threadMethod()
     else
     {
       TftpClient* t = new TftpClient();
-      t->run(ds.getFromIPA(), ds.getFromPort(), (UCHAR*)ds.getData(), ds.getDataLength());
+      t->run(baseDir, ds.getFromIPA(), ds.getFromPort(), (UCHAR*)ds.getData(), ds.getDataLength());
     }
   }
 }
diff --git a/tftpd.h b/tftpd.h
index f866febd0a8c98ed8b4667e1e2085397ebc5c1af..50f2edea7aadc5249eb0000aa8d2c0c832eca5b9 100644 (file)
--- a/tftpd.h
+++ b/tftpd.h
@@ -38,7 +38,7 @@ class Tftpd : public Thread
     Tftpd();
     virtual ~Tftpd();
 
-    int run();
+    int run(char* baseDir);
     int shutdown();
 
   private:
@@ -46,6 +46,8 @@ class Tftpd : public Thread
 
     DatagramSocket ds;
     Log* log;
+
+    char* baseDir;
 };
 
 #endif
index 0eadacb22b105bfae1008cf4d3cf00824623905c..851c024bf438d9618aeae126d034c1cbf45d75b8 100755 (executable)
--- a/thread.c
+++ b/thread.c
@@ -59,7 +59,6 @@ void Thread::threadStop()
   // Signal thread here in case it's waiting
   threadSignal();
   pthread_join(pthread, NULL);
-  this->threadPostStopCleanup();
 }
 
 void Thread::threadCancel()
@@ -67,7 +66,7 @@ void Thread::threadCancel()
   threadActive = 0;
   pthread_cancel(pthread);
   pthread_join(pthread, NULL);
-  this->threadPostStopCleanup();
+  this->threadPostStopCleanup(); // thread was cancelled, did not run post-stop above
 }
 
 void Thread::threadCheckExit()
index 35d2fea1a49c9a846b083e0ae7d523aa0d84c13c..061c1971963a5826fc38b380edb63a860dc6ceaf 100644 (file)
 
 # Override IP = 1
 
+## A file name to send to the MVP. The MVP will then request
+## this file from the TFTP server. Don't use a path here!
+
+# TFTP file name = vomp-dongle
+
 [General]
 
 ## The client auto-detects whether to use PAL or NTSC. If you
index c52e473935dd16193de299483fefb08a30336a06..722c1af9a272d5a3a2affa234d7368cb17a4da5e 100644 (file)
@@ -8,17 +8,23 @@
 ## can enter a name here that will appear on the
 ## server select list on the MVP
 
-# Server name = MyServer
+# Server name = My-Server
 
 ## Enable this to start the built in Bootp server
 ## Required to boot the MVP if you have not got a
 ## DHCP server that can tell the MVP its boot file
 ## name and server
 
-# Bootp server = 1
+# Bootp server enabled = yes
 
 ## 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
+# TFTP server enabled = yes
+
+## Base directory for TFTP server
+## If you leave this blank the plugin config
+## path will be used - i.e. where this file is
+
+# TFTP directory = /tftpboot