SSDP Server - working version provides SSDP based network discovery, and with a companion web server, may provide other functionalities.

Dependents:   X10Svr SSDP_Server

Revision:
2:3d6d70556fca
Parent:
1:def15d0b2fae
Child:
3:85fa421bbcc2
--- a/SSDP.cpp	Tue Jul 03 00:46:34 2018 +0000
+++ b/SSDP.cpp	Tue Jul 10 03:08:15 2018 +0000
@@ -6,8 +6,9 @@
 // 
 #include "SSDP.h"
 #include "EthernetInterface.h"
+#include "SW_String.h"
 
-//#define DEBUG "SSDP"      //Debug is disabled by default
+#define DEBUG "SSDP"      //Debug is disabled by default
 
 #include <cstdio>
 #if (defined(DEBUG) && !defined(TARGET_LPC11U24))
@@ -24,6 +25,7 @@
 
 static const char* MCAST_GRP = "239.255.255.250";
 static const int MCAST_PORT = 1900;
+static Thread * pThr;
 
 // sprintf(buffer, SSDP_HTTP, "myIPString", myPort, "myIdentity", "myIdentity");
 // Requires IP address as a string
@@ -78,20 +80,30 @@
     Endpoint client;
     char buffer[256];
     while (true) {
-        INFO("Wait for packet...");
+        //INFO("Wait for packet...");
         int n = server.receiveFrom(client, buffer, sizeof(buffer)-1);
         buffer[n] = '\0';
         if (n) {
             char * p = buffer;
-            volatile int delay = 1;
+            volatile int delay = 0;
+            uint8_t mask = 0x00;    // fragments we found in the received packet
             
+            //INFO("SSDP\n%s", buffer);
             while (*p) {
                 char * e = strstr(p, "\r\n");
                 if (e && (e - buffer) < n) {
                     *e = '\0';
-                    if (strstr(p, "MX: ")) {
+                    if (sw_stristr(p, "M-SEARCH * HTTP/1.1")) {
+                        mask |= 0x01;                               // M-SEARCH * HTTP/1.1
+                    } else if (sw_stristr(p, "MAN:") && sw_stristr(p,"\"ssdp:discover\"")) {
+                        mask |= 0x02;                               // MAN: "ssdp:discover"
+                    } else if (sw_stristr(p, "MX:")) {
+                        mask |= 0x04;                               // MX: \d
                         delay = atoi(p + 3);
-                    } else if (strstr(p, "HOST: ")) {
+                    } else if (sw_stristr(p, "ST:") && sw_stristr(p, "upnp:rootdevice")) {
+                        mask |= 0x08;
+                    } else if (sw_stristr(p, "HOST: ")) {
+                        mask |= 0x10;                               // HOST: 239.255.255.250:49152
                         char * pColon = strchr(p+6, ':');
                         if (pColon) {
                             pColon = '\0';
@@ -101,13 +113,23 @@
                 }
                 p++;
             }
-            char * out_buffer = (char *)malloc(strlen(SSDP_HTTP) + SSDP_HTTP_OVERHEAD);
-            if (out_buffer) {
-                sprintf(out_buffer, SSDP_HTTP, cfg->ipAddr, cfg->port, cfg->ident, cfg->ident);
-                // It would be polite to delay, but the recommendation is from 1 to 2 seconds
-                // Thread::wait(delay * 1000);
-                server.sendTo(client, out_buffer, strlen(out_buffer));
-                free(out_buffer);
+            //INFO("*********** %02X", mask);
+            if ((mask & 0x1F) == 0x1F) {
+                char * out_buffer = (char *)malloc(strlen(SSDP_HTTP) + SSDP_HTTP_OVERHEAD);
+                
+                if (out_buffer) {
+                    sprintf(out_buffer, SSDP_HTTP, cfg->ipAddr, cfg->port, cfg->ident, cfg->ident);
+                    // It would be polite to delay, but the recommendation is from 1 to 2 seconds.
+                    // Send the response twice, to improve reliability of node discovery
+                    for (int i=0; i<2; i++) {
+                        server.sendTo(client, out_buffer, strlen(out_buffer));
+                        //Thread::wait(150);
+                    }
+                    free(out_buffer);
+                    INFO("SSDPListener: stack-used: %d, total: %d", pThr->max_stack(), pThr->stack_size());
+                } else {
+                    ERR("Can't get memory for response");
+                }
             }
         }
     }
@@ -215,5 +237,5 @@
 }
 
 void SSDP::StartListener() {
-    pThr = new Thread(SSDPListener, (void *)&_config, osPriorityLow);
+    pThr = new Thread(SSDPListener, (void *)&_config, osPriorityLow, 768);
 }