MVP Hx directory locator service added
authorChris Tallon <chris@vomp.tv>
Thu, 4 Jan 2007 16:49:13 +0000 (16:49 +0000)
committerChris Tallon <chris@vomp.tv>
Thu, 4 Jan 2007 16:49:13 +0000 (16:49 +0000)
Makefile
dsock.c
dsock.h
mvprelay.c [new file with mode: 0755]
mvprelay.h [new file with mode: 0755]
mvpserver.c
mvpserver.h
tftpclient.c
udpreplier.c

index 724d89df522567a0084ac7f0740d9e9d70a4fd10..d7d52c322ca4bf435990742e902ed45508085505 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -47,7 +47,7 @@ DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
 ### The object files (add further files here):
 
 OBJS = $(PLUGIN).o dsock.o mvpserver.o udpreplier.o bootpd.o tftpd.o mvpclient.o tcp.o \
-                   ringbuffer.o \
+                   ringbuffer.o mvprelay.o \
                    recplayer.o config.o log.o thread.o mvpreceiver.o tftpclient.o
 
 ### Implicit rules:
diff --git a/dsock.c b/dsock.c
index 885d9273db1e885c45238780efc0b356bd86b8ba..4e7b8d96bc79cc410463ca3dd537427d11046eaa 100644 (file)
--- a/dsock.c
+++ b/dsock.c
@@ -32,7 +32,7 @@ DatagramSocket::~DatagramSocket()
   shutdown();
 }
 
-bool DatagramSocket::init(short port)
+bool DatagramSocket::init(USHORT port)
 {
   myPort = port;
   if ((socketnum = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
@@ -47,7 +47,7 @@ bool DatagramSocket::init(short port)
   memset(&(myAddr.sin_zero), 0, 8);    // zero the rest of the struct
   if (bind(socketnum, (struct sockaddr *)&myAddr, addrlen) == -1)
   {
-    log->log("UDP", Log::CRIT, "Bind error");
+    log->log("UDP", Log::CRIT, "Bind error %u", myPort);
     close(socketnum);
     return false;
   }
@@ -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;
   }
 
@@ -126,19 +126,12 @@ unsigned char DatagramSocket::waitforMessage(unsigned char how)
   */
 }
 
-int DatagramSocket::getDataLength(void) const
-{
-  return mlength;
-}
-
-char *DatagramSocket::getData(void)             {  return buf;  }
-char *DatagramSocket::getFromIPA(void)          {  return fromIPA;  }
-short DatagramSocket::getFromPort(void) const   {  return fromPort; }
-
-void DatagramSocket::send(char *ipa, short port, char *message, int length)
+void DatagramSocket::send(char *ipa, USHORT port, char *message, int length)
 {
   int sentLength = 0;
 
+  //log->log("UDP", Log::DEBUG, "Send port %u", port);
+
   theirAddr.sin_family = AF_INET;      // host byte order
   theirAddr.sin_port = htons(port);    // short, network byte order
   struct in_addr tad;                  // temp struct tad needed to pass to theirAddr.sin_addr
@@ -149,19 +142,72 @@ 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:%u sent length %i", ipa, port, length);
     return;
   }
 
-  log->log("UDP", Log::DEBUG, "%s:%i send failed %i", ipa, port, length);
+  log->log("UDP", Log::DEBUG, "%s:%u send failed %i", ipa, port, length);
 
   sentLength = sendto(socketnum, message, length, 0, (struct sockaddr *)&theirAddr, addrlen);
   if (sentLength == length)
   {
-    log->log("UDP", Log::DEBUG, "%s:%i sent length %i 2nd try", ipa, port, length);
+    log->log("UDP", Log::DEBUG, "%s:%u sent length %i 2nd try", ipa, port, length);
     return;
   }
 
-  log->log("UDP", Log::DEBUG, "%s:%i send failed %i 2nd try", ipa, port, length);
+  log->log("UDP", Log::DEBUG, "%s:%u send failed %i 2nd try", ipa, port, length);
+}
+
+ULONG DatagramSocket::getMyIP(ULONG targetIP)
+{
+  // More friendly interface to below, takes and returns IP in network order
+
+  struct in_addr stargetIP;
+  stargetIP.s_addr = targetIP;
+  struct in_addr ret = myIPforIP(stargetIP);
+  return ret.s_addr;
 }
 
+struct in_addr DatagramSocket::myIPforIP(struct in_addr targetIP)
+{
+  // This function takes a target IP on the network and returns the local IP
+  // that would be used to communicate with it.
+  // This function is static.
+
+  struct in_addr fail;
+  fail.s_addr = 0;
+
+  int zSocket;
+  if ((zSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
+  {
+    Log::getInstance()->log("UDP", Log::CRIT, "Socket error");
+    return fail;
+  }
+
+  struct sockaddr_in zTarget;
+  zTarget.sin_family = AF_INET;
+  zTarget.sin_port = htons(3024); // arbitrary
+  zTarget.sin_addr.s_addr = targetIP.s_addr;
+  memset(&(zTarget.sin_zero), 0, 8);
+
+  if (connect(zSocket, (struct sockaddr *)&zTarget, sizeof(struct sockaddr)) == -1)
+  {
+    Log::getInstance()->log("UDP", Log::CRIT, "Connect error");
+    close(zSocket);
+    return fail;
+  }
+
+  struct sockaddr_in zSource;
+  socklen_t zSourceLen = sizeof(struct sockaddr_in);
+  memset(&zSource, 0, zSourceLen);
+
+  if (getsockname(zSocket, (struct sockaddr*)&zSource, &zSourceLen) == -1)
+  {
+    Log::getInstance()->log("UDP", Log::CRIT, "Getsockname error");
+    close(zSocket);
+    return fail;
+  }
+
+  close(zSocket);
+  return zSource.sin_addr;
+}
diff --git a/dsock.h b/dsock.h
index 388e006d23149633b597918ad066abe9a640d631..9ce3b9d6aa52fa5b1ebcfddb5af36b6cebcb3008 100644 (file)
--- a/dsock.h
+++ b/dsock.h
@@ -32,6 +32,7 @@
 #include <string.h>
 #include <errno.h>
 
+#include "defines.h"
 #include "log.h"
 
 #define MAXBUFLEN 2000
@@ -43,26 +44,31 @@ class DatagramSocket
   public:
     DatagramSocket();
     ~DatagramSocket();
-    bool init(short);                 // port
+    bool init(USHORT);                 // port
     void shutdown();
     unsigned char waitforMessage(unsigned char); // int =0-block =1-new wait =2-continue wait
-    int getDataLength(void) const;
-    char *getData(void);               // returns a pointer to the data
-    char *getFromIPA(void);            // returns a pointer to from IP address
-    short getFromPort(void) const;
-    void send(char *, short, char *, int); // send wants: IP Address ddn style, port,
-                                           // data, length of data
+    void send(char *, USHORT, char *, int); // send wants: IP Address ddn style, port,
+                                            // data, length of data
+
+    char*  getData(void)             { return buf; }      // returns a pointer to the data
+    char*  getFromIPA(void)          { return fromIPA; }  // returns a pointer to from IP address
+    USHORT getFromPort(void) const   { return fromPort; } // returns the sender port number
+    int    getDataLength(void) const { return mlength; }  // returns data length
+
+    ULONG  getMyIP(ULONG targetIP);
+    static struct in_addr myIPforIP(struct in_addr targetIP);
+
   private:
     Log* log;
     int initted;
     int socketnum;                  // Socket descriptor
-    short myPort;                   // My port number
+    USHORT myPort;                  // My port number
     struct sockaddr_in myAddr;      // My address
     struct sockaddr_in theirAddr;   // User address
     socklen_t addrlen;              // length of sockaddr struct
     char buf[MAXBUFLEN];            // main data buffer
     char fromIPA[20];               // from string (ip address)
-    short fromPort;                 // which port user sent on
+    USHORT fromPort;                // which port user sent on
     int mlength;                    // length of message
     struct timeval tv;
     fd_set readfds;
diff --git a/mvprelay.c b/mvprelay.c
new file mode 100755 (executable)
index 0000000..0e49f28
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+    Copyright 2007 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 "mvprelay.h"
+
+MVPRelay::MVPRelay()
+{
+}
+
+MVPRelay::~MVPRelay()
+{
+  shutdown();
+}
+
+int MVPRelay::shutdown()
+{
+  if (threadIsActive()) threadCancel();
+
+  return 1;
+}
+
+int MVPRelay::run()
+{
+  if (threadIsActive()) return 1;
+
+  if (!ds.init(16881))
+  {
+    Log::getInstance()->log("MVPRelay", Log::CRIT, "Could not open UDP 16881");
+    shutdown();
+    return 0;
+  }
+
+  if (!threadStart())
+  {
+    shutdown();
+    return 0;
+  }
+
+  Log::getInstance()->log("MVPRelay", Log::DEBUG, "MVPRelay replier started");
+  return 1;
+}
+
+void MVPRelay::threadMethod()
+{
+  int retval;
+  while(1)
+  {
+    retval = ds.waitforMessage(0);
+    if (retval == 1) continue;
+
+    Log::getInstance()->log("MVPRelay", Log::DEBUG, "MVPRelay request from %s", ds.getFromIPA());
+
+//    TCP::dump((UCHAR*)ds.getData(), ds.getDataLength());
+
+    UCHAR* in = (UCHAR*)ds.getData();
+
+    // Check incoming packet magic number
+
+    ULONG inMagic = ntohl(*(ULONG*)&in[4]);
+    if (inMagic != 0xbabefafe)
+    {
+      Log::getInstance()->log("MVPRelay", Log::DEBUG, "inMagic not correct");
+      continue;
+    }
+
+    // Get peer info
+    USHORT peerPort = ntohs(*(USHORT*)&in[20]);
+
+    // Get my IP for this connection
+    ULONG myIP = ds.getMyIP(*(ULONG*)&in[16]);
+    Log::getInstance()->log("MVPRelay", Log::DEBUG, "Sending my IP as %x", ntohl(myIP));
+
+    // Required return parameters:
+    // -Seq number
+    // -Magic number
+    // -Client IP & port
+    // -First server IP
+
+    // Construct reply packet
+
+    UCHAR out[52];
+    memset(out, 0, 52);
+
+    // Copy sequence number
+    memcpy(out, in, 4);
+
+    // Return magic number is 0xfafebabe
+    *(ULONG*)&out[4] = htonl(0xfafebabe);
+
+    // Copy client IP and port to reply
+    memcpy(&out[16], &in[16], 6);
+
+    // Insert server address
+    *(ULONG*)&out[24] = myIP;
+
+    // Send it
+    ds.send(ds.getFromIPA(), peerPort, (char*)out, 52);
+
+//    TCP::dump(out, 52);
+  }
+}
diff --git a/mvprelay.h b/mvprelay.h
new file mode 100755 (executable)
index 0000000..fd51bfc
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+    Copyright 2007 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 MVPRELAY_H
+#define MVPRELAY_H
+
+#include <stdio.h>
+#include <signal.h>
+
+#include "log.h"
+#include "dsock.h"
+#include "thread.h"
+
+#include "tcp.h" // temp
+
+class MVPRelay : public Thread
+{
+  public:
+    MVPRelay();
+    virtual ~MVPRelay();
+
+    int run();
+    int shutdown();
+
+  private:
+    void threadMethod();
+
+    DatagramSocket ds;
+};
+
+#endif
+
+/*
+
+Protocol information (from the original mvprelay.c)
+
+0  4 bytes: sequence
+4  4 bytes: magic number = 0xBABEFAFE
+8  6 bytes: client MAC address
+14 2 bytes: reserved = 0
+16 4 bytes: client IP address
+20 2 bytes: client port number
+22 2 bytes: reserved = 0
+24 4 bytes: GUI IP address
+28 2 bytes: GUI port number
+30 2 bytes: reserved = 0
+32 4 bytes: Con IP address       ???
+36 2 bytes: Con port number      ???
+38 6 bytes: reserved = 0         ???
+44 4 bytes: Server IP address    ???
+48 2 bytes: Server port number   ???
+50 2 bytes: reserved = 0         ???
+
+Total: 52 bytes
+*/
index 29cecd8d87aa9a3ace7227607c5e63f76b23e2a7..15c0f2cda43714889b4344019ab5244a8cd17b47 100644 (file)
@@ -37,6 +37,7 @@ int MVPServer::stop()
   udpr.shutdown();
   bootpd.shutdown();
   tftpd.shutdown();
+  mvprelay.shutdown();
 
   log.log("Main", Log::INFO, "Stopped main server thread");
   log.shutdown();
@@ -185,6 +186,17 @@ int MVPServer::run(char* tconfigDirExtra)
     log.log("Main", Log::INFO, "Not starting TFTPd");
   }
 
+  // Start mvprelay thread
+  if (!mvprelay.run())
+  {
+    log.log("Main", Log::CRIT, "Could not start MVPRelay");
+    stop();
+    return 0;
+  }
+  else
+  {
+    log.log("Main", Log::INFO, "MVPRelay started");
+  }
 
   // start thread here
   if (!threadStart())
index 48598d78f053f76e8389dc23adfd5b4bd31de3d4..5236f3575c4d3aa2d51c1adb18083dc67f151818 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "defines.h"
 #include "udpreplier.h"
+#include "mvprelay.h"
 #include "bootpd.h"
 #include "tftpd.h"
 #include "mvpclient.h"
@@ -50,6 +51,7 @@ class MVPServer : public Thread
     UDPReplier udpr;
     Bootpd bootpd;
     Tftpd tftpd;
+    MVPRelay mvprelay;
     int listeningSocket;
     char* configDirExtra;
 };
index 8613339c0bbae48d2922a70d5f13931fdbdaf4f0..9a6cb52a403bb84acabfb7d9aff07f3652ced525 100644 (file)
@@ -30,7 +30,6 @@ TftpClient::TftpClient()
 
 TftpClient::~TftpClient()
 {
-  log->log("TftpClient", Log::DEBUG, "Someone calls tftpclient::~tftpclient");
   shutdown();
 }
 
@@ -45,7 +44,7 @@ int TftpClient::shutdown()
     file = NULL;
   }
 
-  log->log("TftpClient", Log::DEBUG, "shutdown");
+  log->log("TftpClient", Log::DEBUG, "Shutdown");
 
   return 1;
 }
@@ -113,7 +112,7 @@ void TftpClient::threadMethod()
       // see if we need to retransmit a data packet
       if (((state == 1) || (state == 2)) && (lastCom < (time(NULL) - 1)))
       {
-//        log->log("TftpClient", Log::DEBUG, "Retransmitting buffer");
+        log->log("TftpClient", Log::DEBUG, "Retransmitting buffer");
         transmitBuffer();
       }
 
@@ -121,8 +120,17 @@ void TftpClient::threadMethod()
     }
     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 (strcmp(ds.getFromIPA(), peerIP))
+      {
+        log->log("TftpClient", Log::ERR, "Not my client IP");
+        continue; // not from my client's IP
+      }
+
+      if (ds.getFromPort() != peerPort)
+      {
+        log->log("TftpClient", Log::ERR, "Not my client port %i %u", ds.getFromPort(), peerPort);
+        continue; // not from my client's port
+      }
 
       if (!processMessage((UCHAR*)ds.getData(), ds.getDataLength()))
       {
@@ -241,12 +249,14 @@ int TftpClient::processAck(UCHAR* data, int length)
     {
       // state == 2, end of transfer. kill connection
       log->log("TftpClient", Log::INFO, "File transfer finished");
+      fclose(file);
+      file = NULL;
       return 0;
     }
   }
   else
   {
-//    log->log("TftpClient", Log::DEBUG, "Ack received for block %i - rejected, retransmitting block\n", ackBlock);
+    log->log("TftpClient", Log::DEBUG, "Ack received for block %i - rejected, retransmitting block\n", ackBlock);
     transmitBuffer();
   }
 
@@ -288,8 +298,6 @@ int TftpClient::sendBlock()
   {
     // end of file
     state = 2;
-    fclose(file);
-    file = NULL;
   }
   else
   {
@@ -303,7 +311,8 @@ int TftpClient::sendBlock()
 
 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 to port %u", blockNumber - 1, peerPort);
 }
index c4b743640dbd7c08cde5245c056e61721306d798..79ff4b334b8fa3475532fe33e223afbf8dcdaad1 100644 (file)
@@ -58,7 +58,7 @@ int UDPReplier::run(char* tserverName)
     return 0;
   }
 
-  Log::getInstance()->log("UDP", Log::DEBUG, "UDP replier started");
+  Log::getInstance()->log("UDPReplier", Log::DEBUG, "UDP replier started");
   return 1;
 }
 
@@ -72,7 +72,7 @@ void UDPReplier::threadMethod()
 
     if (!strcmp(ds.getData(), "VOMP"))
     {
-      Log::getInstance()->log("UDP", Log::DEBUG, "UDP request from %s", ds.getFromIPA());
+      Log::getInstance()->log("UDPReplier", Log::DEBUG, "UDP request from %s", ds.getFromIPA());
       ds.send(ds.getFromIPA(), 3024, serverName, strlen(serverName));
     }
   }