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

Dependents:   X10Svr SSDP_Server

Committer:
WiredHome
Date:
Sun Jul 19 15:07:14 2020 +0000
Revision:
14:ad92261497ca
Parent:
13:bcabd901d344
Change the SSDP listener thread to "normal", and tweak a few debug statements.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
WiredHome 0:f782e7bc66ad 1 //
WiredHome 0:f782e7bc66ad 2 // SSDP Server
WiredHome 0:f782e7bc66ad 3 //
WiredHome 0:f782e7bc66ad 4 // This is an SSDP server. It relies on a web server running on this same node.
WiredHome 0:f782e7bc66ad 5 //
WiredHome 0:f782e7bc66ad 6 //
WiredHome 0:f782e7bc66ad 7 #include "SSDP.h"
WiredHome 0:f782e7bc66ad 8 #include "EthernetInterface.h"
WiredHome 2:3d6d70556fca 9 #include "SW_String.h"
WiredHome 0:f782e7bc66ad 10
WiredHome 10:26f5a66f05a4 11 // Normal discovery
WiredHome 10:26f5a66f05a4 12 // ST: upnp:rootdevice
WiredHome 10:26f5a66f05a4 13 // ST: ssdp:all
WiredHome 10:26f5a66f05a4 14 // Some devices query directly for a Belkin device (like Amazon dot)
WiredHome 10:26f5a66f05a4 15 // ST: urn:Belkin:device:**
WiredHome 10:26f5a66f05a4 16 // define the following to support that discovery
WiredHome 10:26f5a66f05a4 17 #define ST_DISCOVER_BELKIN_DEVICE
WiredHome 10:26f5a66f05a4 18
WiredHome 11:b7f8070014d8 19 #define DEBUG "SSDP" //Debug is disabled by default
WiredHome 0:f782e7bc66ad 20
WiredHome 1:def15d0b2fae 21 #include <cstdio>
WiredHome 1:def15d0b2fae 22 #if (defined(DEBUG) && !defined(TARGET_LPC11U24))
WiredHome 6:9df748509c3d 23 #define DBG(x, ...) std::printf("[DBG %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 6:9df748509c3d 24 #define WARN(x, ...) std::printf("[WRN %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 6:9df748509c3d 25 #define ERR(x, ...) std::printf("[ERR %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 6:9df748509c3d 26 #define INFO(x, ...) std::printf("[INF %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 1:def15d0b2fae 27 #else
WiredHome 1:def15d0b2fae 28 #define DBG(x, ...)
WiredHome 1:def15d0b2fae 29 #define WARN(x, ...)
WiredHome 1:def15d0b2fae 30 #define ERR(x, ...)
WiredHome 1:def15d0b2fae 31 #define INFO(x, ...)
WiredHome 1:def15d0b2fae 32 #endif
WiredHome 0:f782e7bc66ad 33 static const char* MCAST_GRP = "239.255.255.250";
WiredHome 0:f782e7bc66ad 34 static const int MCAST_PORT = 1900;
WiredHome 2:3d6d70556fca 35 static Thread * pThr;
WiredHome 0:f782e7bc66ad 36
WiredHome 0:f782e7bc66ad 37 // sprintf(buffer, SSDP_HTTP, "myIPString", myPort, "myIdentity", "myIdentity");
WiredHome 0:f782e7bc66ad 38 // Requires IP address as a string
WiredHome 0:f782e7bc66ad 39 static const char * SSDP_HTTP =
WiredHome 0:f782e7bc66ad 40 "HTTP/1.1 200 OK\r\n"
WiredHome 0:f782e7bc66ad 41 "CACHE-CONTROL: max-age=1800\r\n"
WiredHome 0:f782e7bc66ad 42 "DATE: Mon, 22 Jun 2015 17:24:01 GMT\r\n"
WiredHome 0:f782e7bc66ad 43 "EXT:\r\n"
WiredHome 0:f782e7bc66ad 44 "LOCATION: http://%s:%d/setup.xml\r\n" // "my.ip.string", portNum
WiredHome 0:f782e7bc66ad 45 "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n"
WiredHome 0:f782e7bc66ad 46 "01-NLS: %s\r\n" // "Unique Identity"
WiredHome 10:26f5a66f05a4 47 "SERVER: Smartware, UPnP/2.0, Smartware\r\n"
WiredHome 0:f782e7bc66ad 48 "ST: upnp:rootdevice\r\n"
WiredHome 0:f782e7bc66ad 49 "USN: uuid:Node-1_0-%s::upnp:rootdevice\r\n" // "Unique Identity"
WiredHome 0:f782e7bc66ad 50 "X-User-Agent: Smartware\r\n"
WiredHome 0:f782e7bc66ad 51 "\r\n";
WiredHome 0:f782e7bc66ad 52
WiredHome 0:f782e7bc66ad 53 // Addr: "###.###.###.###" [15]
WiredHome 0:f782e7bc66ad 54 // Port: 12345 [5]
WiredHome 0:f782e7bc66ad 55 // Ident: "#########0#########0#########0" [30] x 2
WiredHome 0:f782e7bc66ad 56 //
WiredHome 0:f782e7bc66ad 57 #define SSDP_HTTP_OVERHEAD 50 // Number of bytes to fill in the information
WiredHome 0:f782e7bc66ad 58
WiredHome 0:f782e7bc66ad 59
WiredHome 10:26f5a66f05a4 60 // sprintf(buffer, SSDP_NOTIFY_ALIVE, myIPasString, myPort);
WiredHome 0:f782e7bc66ad 61 // Requires IP address as a string
WiredHome 10:26f5a66f05a4 62 static const char * SSDP_NOTIFY_ALIVE =
WiredHome 0:f782e7bc66ad 63 "NOTIFY * HTTP/1.1\r\n"
WiredHome 0:f782e7bc66ad 64 "HOST: 239.255.255.250:1900\r\n"
WiredHome 10:26f5a66f05a4 65 "CACHE-CONTROL: max-age=86400\r\n"
WiredHome 0:f782e7bc66ad 66 "LOCATION: http://%s:%u/setup.xml\r\n"
WiredHome 10:26f5a66f05a4 67 "NT: upnp:rootdevice\r\n"
WiredHome 0:f782e7bc66ad 68 "NTS: ssdp:alive\r\n\r\n"
WiredHome 10:26f5a66f05a4 69 "SERVER: Smartware, UPnP/2.0, Smartware\r\n"
WiredHome 0:f782e7bc66ad 70 "";
WiredHome 0:f782e7bc66ad 71
WiredHome 0:f782e7bc66ad 72 // Addr: "###.###.###.###" [15]
WiredHome 0:f782e7bc66ad 73 // Port: 12345 [5]
WiredHome 0:f782e7bc66ad 74 //
WiredHome 10:26f5a66f05a4 75 #define SSDP_NOTIFY_ALIVE_OVERHEAD 25 // Number of bytes to fill in the information (+5)
WiredHome 0:f782e7bc66ad 76
WiredHome 0:f782e7bc66ad 77
WiredHome 1:def15d0b2fae 78 // The SSDP listener thread
WiredHome 0:f782e7bc66ad 79 static void SSDPListener(void const * args) {
WiredHome 0:f782e7bc66ad 80 UDPSocket server;
WiredHome 14:ad92261497ca 81 SSDP_Config_T * cfg = (SSDP_Config_T*)args;
WiredHome 0:f782e7bc66ad 82
WiredHome 0:f782e7bc66ad 83 server.bind(MCAST_PORT);
WiredHome 13:bcabd901d344 84 int r = server.join_multicast_group(MCAST_GRP);
WiredHome 13:bcabd901d344 85 if (r != 0) {
WiredHome 13:bcabd901d344 86 ERR("Error joining the multicast group, ret: %d", r);
WiredHome 13:bcabd901d344 87 return;
WiredHome 0:f782e7bc66ad 88 }
WiredHome 6:9df748509c3d 89 server.set_blocking(false, 50); // non-blocking with 50ms timeout
WiredHome 0:f782e7bc66ad 90 Endpoint client;
WiredHome 0:f782e7bc66ad 91 char buffer[256];
WiredHome 0:f782e7bc66ad 92 while (true) {
WiredHome 2:3d6d70556fca 93 //INFO("Wait for packet...");
WiredHome 0:f782e7bc66ad 94 int n = server.receiveFrom(client, buffer, sizeof(buffer)-1);
WiredHome 6:9df748509c3d 95 if (n > 0) {
WiredHome 2:3d6d70556fca 96 volatile int delay = 0;
WiredHome 2:3d6d70556fca 97 uint8_t mask = 0x00; // fragments we found in the received packet
WiredHome 0:f782e7bc66ad 98
WiredHome 7:1e8c677e3d28 99 buffer[n] = '\0';
WiredHome 12:4e7c5e1fd32b 100 INFO("SSDP Recv %d bytes from %s:%d", n,
WiredHome 6:9df748509c3d 101 client.get_address(), client.get_port());
WiredHome 14:ad92261497ca 102 INFO("RecvMessage:\r\n<<<<<<<<<<<<<<\r\n%s>>>>>>>>>>>>>>>", buffer);
WiredHome 8:e8f0dc2b78c4 103 char * p = buffer;
WiredHome 0:f782e7bc66ad 104 while (*p) {
WiredHome 0:f782e7bc66ad 105 char * e = strstr(p, "\r\n");
WiredHome 0:f782e7bc66ad 106 if (e && (e - buffer) < n) {
WiredHome 0:f782e7bc66ad 107 *e = '\0';
WiredHome 14:ad92261497ca 108 //INFO("EVAL '%s'", p);
WiredHome 2:3d6d70556fca 109 if (sw_stristr(p, "M-SEARCH * HTTP/1.1")) {
WiredHome 2:3d6d70556fca 110 mask |= 0x01; // M-SEARCH * HTTP/1.1
WiredHome 2:3d6d70556fca 111 } else if (sw_stristr(p, "MAN:") && sw_stristr(p,"\"ssdp:discover\"")) {
WiredHome 2:3d6d70556fca 112 mask |= 0x02; // MAN: "ssdp:discover"
WiredHome 2:3d6d70556fca 113 } else if (sw_stristr(p, "MX:")) {
WiredHome 2:3d6d70556fca 114 mask |= 0x04; // MX: \d
WiredHome 0:f782e7bc66ad 115 delay = atoi(p + 3);
WiredHome 2:3d6d70556fca 116 } else if (sw_stristr(p, "ST:") && sw_stristr(p, "upnp:rootdevice")) {
WiredHome 2:3d6d70556fca 117 mask |= 0x08;
WiredHome 7:1e8c677e3d28 118 } else if (sw_stristr(p, "ST:") && sw_stristr(p, "ssdp:all")) {
WiredHome 7:1e8c677e3d28 119 mask |= 0x08;
WiredHome 10:26f5a66f05a4 120 #ifdef ST_DISCOVER_BELKIN_DEVICE
WiredHome 10:26f5a66f05a4 121 } else if (sw_stristr(p, "ST:") && sw_stristr(p, "urn:Belkin:device:**")) {
WiredHome 10:26f5a66f05a4 122 mask |= 0x08;
WiredHome 11:b7f8070014d8 123 } else if (sw_stristr(p, "ST:") && sw_stristr(p, "urn:Belkin:service:")) {
WiredHome 11:b7f8070014d8 124 mask |= 0x08;
WiredHome 10:26f5a66f05a4 125 #endif
WiredHome 2:3d6d70556fca 126 } else if (sw_stristr(p, "HOST: ")) {
WiredHome 2:3d6d70556fca 127 mask |= 0x10; // HOST: 239.255.255.250:49152
WiredHome 0:f782e7bc66ad 128 char * pColon = strchr(p+6, ':');
WiredHome 0:f782e7bc66ad 129 if (pColon) {
WiredHome 0:f782e7bc66ad 130 pColon = '\0';
WiredHome 0:f782e7bc66ad 131 }
WiredHome 0:f782e7bc66ad 132 }
WiredHome 14:ad92261497ca 133 //INFO(" mask: %02X", mask);
WiredHome 0:f782e7bc66ad 134 p = e + 1;
WiredHome 0:f782e7bc66ad 135 }
WiredHome 0:f782e7bc66ad 136 p++;
WiredHome 0:f782e7bc66ad 137 }
WiredHome 2:3d6d70556fca 138 if ((mask & 0x1F) == 0x1F) {
WiredHome 2:3d6d70556fca 139 char * out_buffer = (char *)malloc(strlen(SSDP_HTTP) + SSDP_HTTP_OVERHEAD);
WiredHome 2:3d6d70556fca 140
WiredHome 10:26f5a66f05a4 141 INFO("\r\n\r\n ***** %02X", mask);
WiredHome 2:3d6d70556fca 142 if (out_buffer) {
WiredHome 2:3d6d70556fca 143 sprintf(out_buffer, SSDP_HTTP, cfg->ipAddr, cfg->port, cfg->ident, cfg->ident);
WiredHome 10:26f5a66f05a4 144 // It would be polite to delay, but the recommendation is from 1 to 5 seconds,
WiredHome 10:26f5a66f05a4 145 // and that will stall this thread.
WiredHome 14:ad92261497ca 146 INFO("SSDPListener: reply >>>>>>> %s:%d >>>>>>>>>>>>>", client.get_address(),
WiredHome 10:26f5a66f05a4 147 client.get_port());
WiredHome 10:26f5a66f05a4 148 INFO("\r\n%s", out_buffer);
WiredHome 10:26f5a66f05a4 149 int i = server.sendTo(client, out_buffer, strlen(out_buffer));
WiredHome 12:4e7c5e1fd32b 150 INFO(" sendTo %3d: reply", i);
WiredHome 2:3d6d70556fca 151 free(out_buffer);
WiredHome 2:3d6d70556fca 152 INFO("SSDPListener: stack-used: %d, total: %d", pThr->max_stack(), pThr->stack_size());
WiredHome 2:3d6d70556fca 153 } else {
WiredHome 2:3d6d70556fca 154 ERR("Can't get memory for response");
WiredHome 2:3d6d70556fca 155 }
WiredHome 0:f782e7bc66ad 156 }
WiredHome 0:f782e7bc66ad 157 }
WiredHome 0:f782e7bc66ad 158 }
WiredHome 0:f782e7bc66ad 159 }
WiredHome 0:f782e7bc66ad 160
WiredHome 0:f782e7bc66ad 161 SSDP::SSDP(const char * name, const char * ident, const char * ipAddr, int port) {
WiredHome 0:f782e7bc66ad 162 pThr = NULL;
WiredHome 0:f782e7bc66ad 163 _config.name = NULL;
WiredHome 0:f782e7bc66ad 164 SetFriendlyName(name);
WiredHome 0:f782e7bc66ad 165 _config.ident = NULL;
WiredHome 0:f782e7bc66ad 166 SetFriendlyName(ident);
WiredHome 0:f782e7bc66ad 167 _config.ipAddr = NULL;
WiredHome 0:f782e7bc66ad 168 SetIPAddress(ipAddr);
WiredHome 0:f782e7bc66ad 169 _config.port = port;
WiredHome 0:f782e7bc66ad 170 StartListener();
WiredHome 1:def15d0b2fae 171 INFO("SSDP(......) constructor done. Listener Started.");
WiredHome 0:f782e7bc66ad 172 SendNotify();
WiredHome 0:f782e7bc66ad 173 }
WiredHome 0:f782e7bc66ad 174
WiredHome 0:f782e7bc66ad 175 SSDP::SSDP(const SSDP_Config_T * config) {
WiredHome 0:f782e7bc66ad 176 pThr = NULL;
WiredHome 0:f782e7bc66ad 177 memcpy(&_config, config, sizeof(SSDP_Config_T));
WiredHome 0:f782e7bc66ad 178 StartListener();
WiredHome 1:def15d0b2fae 179 INFO("SSDP(.) constructor done. Listener Started.");
WiredHome 0:f782e7bc66ad 180 SendNotify();
WiredHome 0:f782e7bc66ad 181 }
WiredHome 0:f782e7bc66ad 182
WiredHome 0:f782e7bc66ad 183 SSDP::~SSDP() {
WiredHome 13:bcabd901d344 184 INFO("Terminate SSDP object, pThr: %p", pThr);
WiredHome 0:f782e7bc66ad 185 if (pThr)
WiredHome 13:bcabd901d344 186 pThr->terminate(); // should terminate SSDPListener
WiredHome 0:f782e7bc66ad 187 pThr = NULL;
WiredHome 0:f782e7bc66ad 188 DelFriendlyName();
WiredHome 0:f782e7bc66ad 189 DelIdentity();
WiredHome 0:f782e7bc66ad 190 DelIPAddress();
WiredHome 0:f782e7bc66ad 191 }
WiredHome 0:f782e7bc66ad 192
WiredHome 10:26f5a66f05a4 193 void SSDP::SendNotify(NotifyType_t nt) {
WiredHome 10:26f5a66f05a4 194 char * out_buffer = (char *)malloc(strlen(SSDP_NOTIFY_ALIVE) + SSDP_NOTIFY_ALIVE_OVERHEAD);
WiredHome 10:26f5a66f05a4 195 (void)nt;
WiredHome 10:26f5a66f05a4 196
WiredHome 0:f782e7bc66ad 197 if (out_buffer) {
WiredHome 0:f782e7bc66ad 198 UDPSocket sock;
WiredHome 1:def15d0b2fae 199 Endpoint broadcast;
WiredHome 10:26f5a66f05a4 200 volatile int i;
WiredHome 5:199656d96c72 201
WiredHome 5:199656d96c72 202 i = sock.init();
WiredHome 9:9b46a499de53 203 INFO(" %d = sock.init()", i);
WiredHome 5:199656d96c72 204 i = sock.set_broadcasting();
WiredHome 9:9b46a499de53 205 INFO(" %d = sock.set_broadcasting()", i);
WiredHome 5:199656d96c72 206 i = broadcast.set_address(MCAST_GRP, MCAST_PORT);
WiredHome 9:9b46a499de53 207 INFO(" %d = sock.set_address(%s,%d)", i, MCAST_GRP, MCAST_PORT);
WiredHome 10:26f5a66f05a4 208 sprintf(out_buffer, SSDP_NOTIFY_ALIVE, _config.ipAddr, _config.port);
WiredHome 12:4e7c5e1fd32b 209 INFO("SendNotify: >>>>>>>>>>>>>>\r\n%s>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>", out_buffer);
WiredHome 5:199656d96c72 210 i = sock.sendTo(broadcast, out_buffer, strlen(out_buffer));
WiredHome 9:9b46a499de53 211 INFO(" %d = sendTo(%s, ..., %d)", i, broadcast.get_address(), strlen(out_buffer));
WiredHome 0:f782e7bc66ad 212 free(out_buffer);
WiredHome 0:f782e7bc66ad 213 }
WiredHome 0:f782e7bc66ad 214 }
WiredHome 0:f782e7bc66ad 215
WiredHome 0:f782e7bc66ad 216 bool SSDP::SetFriendlyName(const char * name) {
WiredHome 0:f782e7bc66ad 217 DelFriendlyName();
WiredHome 0:f782e7bc66ad 218 _config.name = (char *)malloc(strlen(name) + 1);
WiredHome 0:f782e7bc66ad 219 if (_config.name) {
WiredHome 0:f782e7bc66ad 220 strcpy(_config.name, name);
WiredHome 0:f782e7bc66ad 221 return true;
WiredHome 0:f782e7bc66ad 222 } else {
WiredHome 0:f782e7bc66ad 223 return false;
WiredHome 0:f782e7bc66ad 224 }
WiredHome 0:f782e7bc66ad 225 }
WiredHome 0:f782e7bc66ad 226
WiredHome 0:f782e7bc66ad 227 void SSDP::DelFriendlyName() {
WiredHome 0:f782e7bc66ad 228 if (_config.name)
WiredHome 0:f782e7bc66ad 229 free(_config.name);
WiredHome 0:f782e7bc66ad 230 _config.name = NULL;
WiredHome 0:f782e7bc66ad 231 }
WiredHome 0:f782e7bc66ad 232
WiredHome 0:f782e7bc66ad 233 bool SSDP::SetIdentity(const char * ident) {
WiredHome 0:f782e7bc66ad 234 DelIdentity();
WiredHome 0:f782e7bc66ad 235 _config.ident = (char *)malloc(strlen(ident) + 1);
WiredHome 0:f782e7bc66ad 236 if (_config.ident) {
WiredHome 0:f782e7bc66ad 237 strcpy(_config.ident, ident);
WiredHome 0:f782e7bc66ad 238 return true;
WiredHome 0:f782e7bc66ad 239 } else {
WiredHome 0:f782e7bc66ad 240 return false;
WiredHome 0:f782e7bc66ad 241 }
WiredHome 0:f782e7bc66ad 242 }
WiredHome 0:f782e7bc66ad 243
WiredHome 0:f782e7bc66ad 244 void SSDP::DelIdentity() {
WiredHome 0:f782e7bc66ad 245 if (_config.ident)
WiredHome 0:f782e7bc66ad 246 free(_config.ident);
WiredHome 0:f782e7bc66ad 247 _config.ident = NULL;
WiredHome 0:f782e7bc66ad 248 }
WiredHome 0:f782e7bc66ad 249
WiredHome 0:f782e7bc66ad 250 bool SSDP::SetIPAddress(const char * ipAddr) {
WiredHome 0:f782e7bc66ad 251 DelIPAddress();
WiredHome 0:f782e7bc66ad 252 _config.ipAddr = (char *)malloc(strlen(ipAddr) + 1);
WiredHome 0:f782e7bc66ad 253 if (_config.ipAddr) {
WiredHome 0:f782e7bc66ad 254 strcpy(_config.ipAddr, ipAddr);
WiredHome 0:f782e7bc66ad 255 return true;
WiredHome 0:f782e7bc66ad 256 } else {
WiredHome 0:f782e7bc66ad 257 return false;
WiredHome 0:f782e7bc66ad 258 }
WiredHome 0:f782e7bc66ad 259 }
WiredHome 0:f782e7bc66ad 260
WiredHome 0:f782e7bc66ad 261 void SSDP::DelIPAddress() {
WiredHome 0:f782e7bc66ad 262 if (_config.ipAddr)
WiredHome 0:f782e7bc66ad 263 free(_config.ipAddr);
WiredHome 0:f782e7bc66ad 264 _config.ipAddr = NULL;
WiredHome 0:f782e7bc66ad 265 }
WiredHome 0:f782e7bc66ad 266
WiredHome 0:f782e7bc66ad 267 bool SSDP::SetPort(int port) {
WiredHome 0:f782e7bc66ad 268 _config.port = port;
WiredHome 0:f782e7bc66ad 269 return true;
WiredHome 0:f782e7bc66ad 270 }
WiredHome 0:f782e7bc66ad 271
WiredHome 0:f782e7bc66ad 272 void SSDP::StartListener() {
WiredHome 14:ad92261497ca 273 pThr = new Thread(SSDPListener, (void *)&_config, osPriorityNormal, 768);
WiredHome 13:bcabd901d344 274 INFO("SSDP Listener Started: %p", pThr);
WiredHome 0:f782e7bc66ad 275 }
WiredHome 10:26f5a66f05a4 276
WiredHome 10:26f5a66f05a4 277
WiredHome 10:26f5a66f05a4 278 #if 0 // simple UUID generator is needed
WiredHome 10:26f5a66f05a4 279 char GUID[40];
WiredHome 10:26f5a66f05a4 280
WiredHome 10:26f5a66f05a4 281 // srand (clock());
WiredHome 10:26f5a66f05a4 282 // UUIDGenerator(GUID, sizeof(GUID));
WiredHome 10:26f5a66f05a4 283 // printf ("%s\r\n", GUID);
WiredHome 10:26f5a66f05a4 284
WiredHome 10:26f5a66f05a4 285 /// Simple UUID Generator.
WiredHome 10:26f5a66f05a4 286 ///
WiredHome 10:26f5a66f05a4 287 /// This is not claimed to be particularly good, but it does generally meet
WiredHome 10:26f5a66f05a4 288 /// the minimum requirements for a valid UUID.
WiredHome 10:26f5a66f05a4 289 ///
WiredHome 10:26f5a66f05a4 290 /// @param UUID is a pointer to a buffer into which the UUID will be written.
WiredHome 10:26f5a66f05a4 291 /// @param UUID_size is that size of that buffer, and is used to ensure the
WiredHome 10:26f5a66f05a4 292 /// buffer is large enough.
WiredHome 10:26f5a66f05a4 293 /// @returns true if a UUID was successfully generated into the provided buffer.
WiredHome 10:26f5a66f05a4 294 ///
WiredHome 10:26f5a66f05a4 295 bool UUIDGenerator(char * UUID, size_t UUID_size) {
WiredHome 10:26f5a66f05a4 296 int t = 0;
WiredHome 10:26f5a66f05a4 297 char *szTemp = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx";
WiredHome 10:26f5a66f05a4 298 char *szHex = "0123456789ABCDEF-";
WiredHome 10:26f5a66f05a4 299 int nLen = strlen (szTemp);
WiredHome 10:26f5a66f05a4 300
WiredHome 10:26f5a66f05a4 301 if (UUID_size < 40)
WiredHome 10:26f5a66f05a4 302 return false;
WiredHome 10:26f5a66f05a4 303
WiredHome 10:26f5a66f05a4 304 for (t=0; t<nLen+1; t++)
WiredHome 10:26f5a66f05a4 305 {
WiredHome 10:26f5a66f05a4 306 int r = rand () % 16;
WiredHome 10:26f5a66f05a4 307 char c = ' ';
WiredHome 10:26f5a66f05a4 308
WiredHome 10:26f5a66f05a4 309 switch (szTemp[t])
WiredHome 10:26f5a66f05a4 310 {
WiredHome 10:26f5a66f05a4 311 case 'x' : { c = szHex [r]; } break;
WiredHome 10:26f5a66f05a4 312 case 'y' : { c = szHex [r & 0x03 | 0x08]; } break;
WiredHome 10:26f5a66f05a4 313 case '-' : { c = '-'; } break;
WiredHome 10:26f5a66f05a4 314 case '4' : { c = '4'; } break;
WiredHome 10:26f5a66f05a4 315 }
WiredHome 10:26f5a66f05a4 316 UUID[t] = ( t < nLen ) ? c : 0x00;
WiredHome 10:26f5a66f05a4 317 }
WiredHome 10:26f5a66f05a4 318 return true;
WiredHome 10:26f5a66f05a4 319 }
WiredHome 10:26f5a66f05a4 320 #endif