]> git.vomp.tv Git - vompclient.git/commitdiff
IPv6 support for discovery protocol
authorChris Tallon <chris@vomp.tv>
Tue, 15 Oct 2019 16:08:39 +0000 (17:08 +0100)
committerChris Tallon <chris@vomp.tv>
Tue, 15 Oct 2019 16:08:39 +0000 (17:08 +0100)
GNUmakefile
objects.mk
tcp.cc
vdp6.cc [new file with mode: 0644]
vdp6.h [new file with mode: 0644]
vdr.cc
vdr.h

index d84161110af7c9db654635e19ad6a92ac30e00d7..82fd3e0fb60282678f560006d3a5bee762c117c4 100644 (file)
@@ -3,7 +3,7 @@ vomp_platform=$(shell ./select-platform)
 #vomp_platform=crossraspberry
 $(info selected $(vomp_platform))
 
-vomp_options=
+vomp_options=-DIPV6
 # uncomment the line below if you want to build vomp application without a reboot option, automatically set for windows!
 #vomp_options+= -DVOMP_HAS_EXIT
 
index a2563da3ee342601a2131b6763c12ee8ba56092b..77dc1d7799679f755fe1e29f24afa313c93cc430 100644 (file)
@@ -1,28 +1,20 @@
-OBJECTS1 = command.o  tcp.o dsock.o thread.o timers.o i18n.o       \
-           message.o messagequeue.o udp.o wol.o audio.o video.o log.o  mutex.o    \
+OBJECTS1 = command.o tcp.o dsock.o thread.o timers.o i18n.o vdp6.o               \
+           message.o messagequeue.o udp.o wol.o audio.o video.o log.o mutex.o    \
            vdr.o recman.o recording.o recinfo.o channel.o rectimer.o event.o     \
-           directory.o mark.o option.o                                           \
-           player.o playerradio.o vfeed.o afeed.o                                \
-           demuxer.o demuxervdr.o demuxerts.o stream.o            \
-           region.o colour.o boxstack.o boxx.o tbboxx.o                          \
-           vinfo.o vquestion.o vrecordinglist.o vrecordinglistclassic.o vrecordinglistadvanced.o vrecording.o \
-           vepgsummary.o vepglistadvanced.o \
+           directory.o mark.o option.o player.o playerradio.o vfeed.o afeed.o    \
+           demuxer.o demuxervdr.o demuxerts.o stream.o                           \
+           region.o colour.o boxstack.o boxx.o tbboxx.o vrecording.o             \
+           vinfo.o vquestion.o vrecordinglist.o vrecordinglistclassic.o          \
+           vrecordinglistadvanced.o vepgsummary.o vepglistadvanced.o             \
            vmute.o vvolume.o vtimerlist.o vtimeredit.o vrecordingmenu.o          \
            vchannellist.o vwelcome.o vvideorec.o vepgsettimer.o                  \
            vchannelselect.o vserverselect.o vconnect.o vepg.o vrecmove.o         \
            vradiorec.o vaudioselector.o vscreensaver.o vopts.o                   \
-           wselectlist.o wjpeg.o wsymbol.o wbutton.o wtextbox.o           \
-           woptionpane.o woptionbox.o wremoteconfig.o wtabbar.o                  \
-           remote.o led.o mtd.o  osd.o surface.o     \
-            vpicturebanner.o                                 \
-            abstractoption.o                         \
+           wselectlist.o wjpeg.o wsymbol.o wbutton.o wtextbox.o                  \
+           woptionpane.o woptionbox.o wremoteconfig.o wtabbar.o led.o            \
+           remote.o mtd.o osd.o surface.o vpicturebanner.o abstractoption.o      \
            eventdispatcher.o vdrrequestpacket.o vdrresponsepacket.o              \
-           vvideolivetv.o vsleeptimer.o                                          \
-           playerlivetv.o playerliveradio.o                                      \
-           wprogressbar.o                                                        \
-           bitmap.o dvbsubtitles.o                                               \
-            tfeed.o vteletextview.o teletextdecodervbiebu.o        \
-           teletxt/txtfont.o  movieinfo.o seriesinfo.o wmovieview.o wseriesview.o tvmedia.o wtvmedia.o\
-           wpictureview.o
-           
-
+           vvideolivetv.o vsleeptimer.o playerlivetv.o playerliveradio.o         \
+           wprogressbar.o bitmap.o dvbsubtitles.o tfeed.o vteletextview.o        \
+           teletextdecodervbiebu.o teletxt/txtfont.o movieinfo.o seriesinfo.o    \
+           wmovieview.o wseriesview.o tvmedia.o wtvmedia.o wpictureview.o
diff --git a/tcp.cc b/tcp.cc
index 43f8e131c9e29e9b213c7e026ce3c05010260f62..fb66acede27f00aae5ace23799f6f4c9940d4023 100644 (file)
--- a/tcp.cc
+++ b/tcp.cc
@@ -150,6 +150,7 @@ int TCP::connectTo(char* host, unsigned short port)
   hints.ai_socktype = SOCK_STREAM;
   if (getaddrinfo(host, portstring, &hints, &res))
   {
+    //printf("[%s] [%s]\n", host, portstring);
     return 0;
   }
 
diff --git a/vdp6.cc b/vdp6.cc
new file mode 100644 (file)
index 0000000..69d70d3
--- /dev/null
+++ b/vdp6.cc
@@ -0,0 +1,149 @@
+/*
+    Copyright 2019 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, see <https://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "defines.h"
+#include "vdr.h"
+#include "log.h"
+#include "vdp6.h"
+
+#if IPV6
+
+VDP6::VDP6()
+{
+}
+
+void VDP6::run()
+{
+  Log* logger = Log::getInstance();
+
+  if (pipe2(pfds, O_NONBLOCK) == -1)
+  {
+    logger->log("VDP6", Log::ERR, "pipe2 error");
+    return;
+  }
+  
+  sock = socket(AF_INET6, SOCK_DGRAM, 0);
+  if (sock < 0)
+  {
+    logger->log("VDP6", Log::ERR, "socket error");
+    return;
+  }
+
+  struct sockaddr_in6 saddr;
+  memset(&saddr, 0, sizeof(saddr));
+  saddr.sin6_family = AF_INET6;
+  inet_pton(AF_INET6, "ff15:766f:6d70:2064:6973:636f:7665:7279", &saddr.sin6_addr);
+  saddr.sin6_port = htons(51056);
+
+  receiveThread = std::thread( [this, logger]
+  {
+    socklen_t addrlen = sizeof(struct sockaddr_in6);
+    char vdpreply[1000];
+    fd_set readfds;
+    struct timeval timeout;
+    timeout.tv_sec = 1;
+    timeout.tv_usec = 500000;
+
+    while(1)
+    {
+      FD_ZERO(&readfds);
+      FD_SET(sock, &readfds);
+      FD_SET(pfds[0], &readfds);
+
+      int sresult = select(((sock > pfds[0]) ? sock : pfds[0]) + 1, &readfds, NULL, NULL, &timeout);
+      if (sresult < 1) break;
+
+      if (FD_ISSET(pfds[0], &readfds)) break;                        
+                              
+      int mlength;
+      struct sockaddr_in6 theirAddr;
+      mlength = recvfrom(sock, vdpreply, 1000, 0, (struct sockaddr *)&theirAddr, &addrlen);
+      if (mlength == -1)
+      {
+        logger->log("VDP6", Log::ERR, "recvfrom error");
+        break;
+      }
+      
+      VDRServer newServer;
+      // FIXME upgrade this to look for a return IP in the reply packet
+      newServer.ip = new char[40];
+      inet_ntop(AF_INET6, &theirAddr.sin6_addr, newServer.ip, sizeof(theirAddr));
+
+      USHORT tempPort;
+      memcpy(&tempPort, &vdpreply[26], 2);
+      newServer.port = ntohs(tempPort);
+
+      ULONG newServerVersion;
+      memcpy(&newServerVersion, &vdpreply[28], 4);
+      newServer.version = ntohl(newServerVersion);
+
+      int newServerNameLength = mlength - 32;
+      newServer.name = new char[newServerNameLength];
+      strcpy(newServer.name, &vdpreply[32]);
+
+      logger->log("VDP6", Log::INFO, "Got response: %s %u %s %lx", newServer.ip, newServer.port, newServer.name, newServer.version);
+      servers.push_back(newServer);
+    }
+  });
+
+  char message[15];
+  memset(message, 0, 15);
+  strcpy(message, "VDP-0001");
+
+  struct if_nameindex* ifs = if_nameindex();
+  int ifIndex;
+
+  for(int i = 0; ifs[i].if_index > 0; i++)
+  {
+    ifIndex = ifs[i].if_index;
+    int d = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifIndex, sizeof(ifIndex));
+    d = sendto(sock, message, 15, 0, (struct sockaddr*)&saddr, sizeof(saddr));
+    if (d > 0) logger->log("VDP6", Log::DEBUG, "Transmitted IPv6 MC UDP on %s", ifs[i].if_name);
+  }
+
+  if_freenameindex(ifs);
+}
+
+int VDP6::numFound()
+{
+  return servers.size();
+}
+
+void VDP6::stop()
+{
+  write(pfds[1], "X", 1);
+  receiveThread.join();
+  
+  close(pfds[0]);
+  close(pfds[1]);
+  close(sock);
+}
+
+#endif
diff --git a/vdp6.h b/vdp6.h
new file mode 100644 (file)
index 0000000..8a4869d
--- /dev/null
+++ b/vdp6.h
@@ -0,0 +1,57 @@
+/*
+    Copyright 2019 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, see <https://www.gnu.org/licenses/>.
+*/
+
+#ifndef VDP_H
+#define VDP_H
+
+#include <thread>
+#include <vector>
+
+#if IPV6
+
+class VDRServer;
+
+/*
+ * Until VDP is reorganised, getServers must be called after stop
+ * and the buffers pointed to by the VDRServer structs must be freed
+ * by the caller.
+ */
+
+class VDP6
+{
+  public:
+    VDP6();
+
+    void run();
+    void stop();
+    int numFound();
+    vector<VDRServer>* getServers() { return &servers; }
+
+  private:
+    int pfds[2];
+    int sock;
+    std::thread receiveThread;
+    vector<VDRServer> servers;
+};
+
+#endif
+
+
+
+#endif
diff --git a/vdr.cc b/vdr.cc
index e8da6067d325ab9b1e82a0943ea870747c9927d9..438aec151020e80f63d5e3dabff21c51d62cbb7a 100644 (file)
--- a/vdr.cc
+++ b/vdr.cc
@@ -14,8 +14,7 @@
     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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+    along with VOMP.  If not, see <https://www.gnu.org/licenses/>.
 */
 
 #include "vdr.h"
@@ -31,6 +30,7 @@
 #include "vdrrequestpacket.h"
 #include "vdrresponsepacket.h"
 #include "command.h"
+#include "vdp6.h"
 #ifdef VOMP_MEDIAPLAYER
 #include "media.h"
 #include "mediaprovider.h"
@@ -171,6 +171,15 @@ void VDR::findServers(vector<VDRServer>& servers)
   strcpy(message, "VDP-0001");
   /*tcp->getMAC(&message[9]); put mac here when TCP modified to do this*/
 
+#if IPV6
+  // FIXME Horrible hack. Rewrite all this.
+  // Change away from relying on the dsock select to do the timing
+  // Do timing here and let UDP4 / UDP6 objects/threads just wait
+  // for responses
+  VDP6 vdp6;
+  vdp6.run();
+#endif
+
   DatagramSocket ds(0);
   int haveAtLeastOne = 0;
   int retval;
@@ -223,6 +232,10 @@ void VDR::findServers(vector<VDRServer>& servers)
     else
     {
       if (haveAtLeastOne) break;
+#if IPV6
+      if (vdp6.numFound()) break;
+#endif
+
       waitType = 1;
       firstloop = false;
 /* For DEBUGGING *
@@ -234,12 +247,39 @@ void VDR::findServers(vector<VDRServer>& servers)
       servers.push_back(newServer);
       waitType = 2;
       haveAtLeastOne = 1;}/ * */
+    }
+  }
+  logger->log("VDR", Log::NOTICE, "END loop");
 
+#if IPV6
+  vdp6.stop();
+  vector<VDRServer>* servers6 = vdp6.getServers();
+  
+  // Add IPv6 found servers to servers vector, if not in servers already
+  // Free buffers from VDRServer objects if not taken. (Itching for that rewrite already).
+
+  for(auto i6 = servers6->begin(); i6 != servers6->end(); i6++)
+  {
+    bool found = false;
 
+    for(auto i4 = servers.begin(); i4 != servers.end(); i4++)
+    {
+      if (!strcmp(i4->name, i6->name)) { found = true; break; }
+    }
 
+    if (found)
+    {
+      delete[] i6->name;
+      delete[] i6->ip;
+    }
+    else
+    {
+      servers.push_back(*i6);
     }
   }
-  logger->log("VDR", Log::NOTICE, "END loop");
+
+#endif
+
   sort(servers.begin(), servers.end(), ServerSorter());
 }
 
diff --git a/vdr.h b/vdr.h
index 0994cb0ec0247f1645073d8049448c042daf3888..dce28c1d0175652afaf55454f07afbfb692f1734 100644 (file)
--- a/vdr.h
+++ b/vdr.h
@@ -253,7 +253,7 @@ public ExternLogger
     int findingServer;
     TCP* tcp;
     int port;
-    char serverIP[16];
+    char serverIP[40];
     USHORT serverPort;
     bool connected;
     ULONG maxChannelNumber;