From 900c5f53e08aacb9e391ba9de400e82ee528afe3 Mon Sep 17 00:00:00 2001 From: Chris Tallon Date: Mon, 7 Jan 2013 17:30:39 +0000 Subject: [PATCH] New VOMP discovery protocol --- mvpserver.c | 20 ++++++++++++--- mvpserver.h | 1 + udpreplier.c | 63 ++++++++++++++++++++++++++++++++++++++-------- udpreplier.h | 5 ++-- vompclientrrproc.c | 15 +++++++---- vompclientrrproc.h | 2 ++ 6 files changed, 85 insertions(+), 21 deletions(-) diff --git a/mvpserver.c b/mvpserver.c index 9a2eabf..8ae63b8 100644 --- a/mvpserver.c +++ b/mvpserver.c @@ -29,6 +29,7 @@ MVPServer::MVPServer() { // MH in case anbody has a better position :-) pthread_mutex_init(&threadClientMutex, NULL); + tcpServerPort = 0; } MVPServer::~MVPServer() @@ -91,6 +92,12 @@ int MVPServer::run(char* tconfigDir) dsyslog("VOMP: Logging disabled"); } + // Get UDP port number for discovery service + + int fail = 1; + int udpport = config.getValueLong("General", "UDP port", &fail); + if (fail) udpport = 51051; + // Work out a name for this server char* serverName; @@ -100,13 +107,18 @@ int MVPServer::run(char* tconfigDir) if (!serverName) // If not, get the hostname { serverName = new char[1024]; - if (gethostname(serverName, 1024)) // if not, just use "-" + if (gethostname(serverName, 1024)) // if not, set default { - strcpy(serverName, "-"); + strcpy(serverName, "VOMP Server"); } } - int udpSuccess = udpr.run(serverName); + // Get VOMP server TCP port to give to UDP replier to put in packets + fail = 1; + tcpServerPort = config.getValueLong("General", "TCP port", &fail); + if (fail) tcpServerPort = 3024; + + int udpSuccess = udpr.run(udpport, serverName, tcpServerPort); delete[] serverName; @@ -232,7 +244,7 @@ void MVPServer::threadMethod() struct sockaddr_in address; address.sin_family = AF_INET; - address.sin_port = htons(3024); + address.sin_port = htons(tcpServerPort); address.sin_addr.s_addr = INADDR_ANY; socklen_t length = sizeof(address); diff --git a/mvpserver.h b/mvpserver.h index 07ca1c9..80cc211 100644 --- a/mvpserver.h +++ b/mvpserver.h @@ -54,6 +54,7 @@ class MVPServer : public Thread MVPRelay mvprelay; int listeningSocket; char* configDir; + USHORT tcpServerPort; }; #endif diff --git a/udpreplier.c b/udpreplier.c index 0b43e17..a98a1e2 100644 --- a/udpreplier.c +++ b/udpreplier.c @@ -18,11 +18,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "vompclientrrproc.h" + #include "udpreplier.h" UDPReplier::UDPReplier() { - serverName = NULL; + message = NULL; + messageLen = 0; } UDPReplier::~UDPReplier() @@ -34,19 +37,59 @@ int UDPReplier::shutdown() { if (threadIsActive()) threadCancel(); - if (serverName) delete[] serverName; - serverName = NULL; + if (message) delete[] message; + message = NULL; return 1; } -int UDPReplier::run(char* tserverName) +int UDPReplier::run(USHORT port, char* serverName, USHORT serverPort) { if (threadIsActive()) return 1; - serverName = new char[strlen(tserverName)+1]; - strcpy(serverName, tserverName); - - if (!ds.init(3024)) + /* + VOMP Discovery Protocol V1 + + Client transmits: "VDP-0001\0<6-byte MAC>" on ports 51051-51055 + + Server responds: + + Field 1 p0: 9 bytes "VDP-0002\0" + + Field 2 p9, 1 byte: + + 0 = no IP specified + 4 = first 4 bytes of field 2 are IPv4 address of server + 6 = field 2 16 bytes are IPv6 address of server + + Field 3, p10, 16 bytes: + As described above. If field 1 is 0, this should be all zeros. If this is an IPv4 address, remaining bytes should be zeros. + + Field 4 p26, 2 bytes: + Port number of server + + Field 5 p28, 4 bytes: + VOMP protocol version (defined in vdr.cc) + + Field 6 p32, variable length + String of server name, null terminated + */ + + messageLen = strlen(serverName) + 33; + message = new char[messageLen]; + memset(message, 0, messageLen); + // by zeroing the packet, this sets no ip address return information + + strcpy(message, "VDP-0002"); + + USHORT temp = htons(serverPort); + memcpy(&message[26], &temp, 2); + + ULONG temp2 = htonl(VompClientRRProc::getProtocolVersion()); + memcpy(&message[28], &temp2, 4); + + strcpy(&message[32], serverName); + + if (!ds.init(port)) { shutdown(); return 0; @@ -70,10 +113,10 @@ void UDPReplier::threadMethod() retval = ds.waitforMessage(0); if (retval == 1) continue; - if (!strcmp(ds.getData(), "VOMP")) + if (!strncmp(ds.getData(), "VDP-0001", 8)) { Log::getInstance()->log("UDPReplier", Log::DEBUG, "UDP request from %s", ds.getFromIPA()); - ds.send(ds.getFromIPA(), 3024, serverName, strlen(serverName)); + ds.send(ds.getFromIPA(), ds.getFromPort(), message, messageLen); } } } diff --git a/udpreplier.h b/udpreplier.h index a287189..9383d84 100644 --- a/udpreplier.h +++ b/udpreplier.h @@ -34,14 +34,15 @@ class UDPReplier : public Thread UDPReplier(); virtual ~UDPReplier(); - int run(char* tserverName); + int run(USHORT udpPort, char* serverName, USHORT serverPort); int shutdown(); private: void threadMethod(); DatagramSocket ds; - char* serverName; + char* message; + int messageLen; }; #endif diff --git a/vompclientrrproc.c b/vompclientrrproc.c index ae670cf..c313ce8 100644 --- a/vompclientrrproc.c +++ b/vompclientrrproc.c @@ -42,14 +42,19 @@ bool ResumeIDLock; -#define VOMP_PROTOCOLL_VERSION 0x00000100 +ULONG VompClientRRProc::VOMP_PROTOCOL_VERSION = 0x00000100; // format is aabbccdd -// cc is release protocol version, increase with every release, that changes protocoll +// cc is release protocol version, increase with every release, that changes protocol // dd is development protocol version, set to zero at every release, -// increase for every protocoll change in git -// bb not equal zero should indicate a non loggytronic protocoll +// increase for every protocol change in git +// bb not equal zero should indicate a non loggytronic protocol // aa is reserved for future use +ULONG VompClientRRProc::getProtocolVersion() +{ + return VOMP_PROTOCOL_VERSION; +} + VompClientRRProc::VompClientRRProc(VompClient& x) : x(x) { @@ -309,7 +314,7 @@ int VompClientRRProc::processLogin() resp->addULONG(timeNow); resp->addLONG(timeOffset); - resp->addULONG(VOMP_PROTOCOLL_VERSION); + resp->addULONG(VOMP_PROTOCOL_VERSION); resp->finalise(); x.tcp.sendPacket(resp->getPtr(), resp->getLen()); log->log("RRProc", Log::DEBUG, "written login reply len %lu", resp->getLen()); diff --git a/vompclientrrproc.h b/vompclientrrproc.h index 535766c..8e7bc7b 100644 --- a/vompclientrrproc.h +++ b/vompclientrrproc.h @@ -52,6 +52,7 @@ class VompClientRRProc : public Thread public: VompClientRRProc(VompClient& x); ~VompClientRRProc(); + static ULONG getProtocolVersion(); bool init(); bool recvRequest(RequestPacket*); @@ -99,6 +100,7 @@ class VompClientRRProc : public Thread RequestPacket* req; RequestPacketQueue req_queue; ResponsePacket* resp; + static ULONG VOMP_PROTOCOL_VERSION; Log* log; }; -- 2.39.2