@@ -26,25 +26,36 @@ License (MIT license):
26
26
27
27
*/
28
28
#define LWIP_OPEN_SRC
29
+ #include < functional>
29
30
#include " ESP8266SSDP.h"
31
+ #include " WiFiUdp.h"
32
+ #include " debug.h"
30
33
31
34
extern " C" {
35
+ #include " osapi.h"
36
+ #include " ets_sys.h"
32
37
#include " user_interface.h"
33
- #include " mem.h"
34
38
}
35
- #include " lwip/ip_addr.h"
39
+
40
+ #include " lwip/opt.h"
41
+ #include " lwip/udp.h"
42
+ #include " lwip/inet.h"
36
43
#include " lwip/igmp.h"
44
+ #include " lwip/mem.h"
45
+ #include " include/UdpContext.h"
37
46
38
- // #define DEBUG_SSDP Serial
47
+ // #define DEBUG_SSDP Serial
39
48
40
49
#define SSDP_INTERVAL 1200
41
50
#define SSDP_PORT 1900
42
51
#define SSDP_METHOD_SIZE 10
43
52
#define SSDP_URI_SIZE 2
44
53
#define SSDP_BUFFER_SIZE 64
45
-
54
+ # define SSDP_MULTICAST_TTL 1
46
55
static const IPAddress SSDP_MULTICAST_ADDR (239 , 255 , 255 , 250 );
47
56
57
+
58
+
48
59
static const char * _ssdp_response_template =
49
60
" HTTP/1.1 200 OK\r\n "
50
61
" EXT:\r\n "
@@ -108,7 +119,17 @@ static const char* _ssdp_schema_template =
108
119
" </root>\r\n "
109
120
" \r\n " ;
110
121
111
- SSDPClass::SSDPClass (){
122
+
123
+ struct SSDPTimer {
124
+ ETSTimer timer;
125
+ };
126
+
127
+ SSDPClass::SSDPClass () :
128
+ _server(0 ),
129
+ _port(80 ),
130
+ _pending(false ),
131
+ _timer(new SSDPTimer)
132
+ {
112
133
_uuid[0 ] = ' \0 ' ;
113
134
_modelNumber[0 ] = ' \0 ' ;
114
135
_friendlyName[0 ] = ' \0 ' ;
@@ -119,65 +140,95 @@ SSDPClass::SSDPClass(){
119
140
_manufacturer[0 ] = ' \0 ' ;
120
141
_manufacturerURL[0 ] = ' \0 ' ;
121
142
sprintf (_schemaURL, " ssdp/schema.xml" );
122
- _port = 80 ;
123
- _pending = false ;
124
143
}
125
144
126
145
SSDPClass::~SSDPClass (){
146
+ delete _timer;
127
147
}
128
148
129
- void SSDPClass::begin (){
130
- ip_addr_t ifaddr;
131
- ip_addr_t multicast_addr;
132
-
149
+ bool SSDPClass::begin (){
133
150
_pending = false ;
134
-
135
- ifaddr.addr = WiFi.localIP ();
136
- multicast_addr.addr = (uint32_t ) SSDP_MULTICAST_ADDR;
137
- igmp_joingroup (&ifaddr, &multicast_addr);
138
-
139
- uint8_t mac[6 ];
140
- WiFi.macAddress (mac);
151
+
141
152
uint32_t chipId = ESP.getChipId ();
142
- sprintf (_uuid, " 38323636-4558-%04x-%04x-%02x%02x%02x%02x%02x%02x" ,
143
- (chipId >> 16 ) & 0xFFFF , chipId & 0xFFFF ,
144
- mac[0 ], mac[1 ], mac[2 ], mac[3 ], mac[4 ], mac[5 ]
145
- );
153
+ sprintf (_uuid, " 38323636-4558-4dda-9188-cda0e6%02x%02x%02x" ,
154
+ (uint16_t ) ((chipId >> 16 ) & 0xff ),
155
+ (uint16_t ) ((chipId >> 8 ) & 0xff ),
156
+ (uint16_t ) chipId & 0xff );
157
+
146
158
#ifdef DEBUG_SSDP
147
159
DEBUG_SSDP.printf (" SSDP UUID: %s\n " , (char *)_uuid);
148
160
#endif
149
- _server.begin (SSDP_PORT);
150
- }
151
161
152
- void SSDPClass::_send (ssdp_method_t method){
153
- #ifdef DEBUG_SSDP
154
- if (method == NONE){
155
- DEBUG_SSDP.print (" Sending Response to " );
156
- DEBUG_SSDP.print (_server.remoteIP ());
157
- DEBUG_SSDP.print (" :" );
158
- DEBUG_SSDP.println (_server.remotePort ());
159
- }else if (method == NOTIFY){
160
- DEBUG_SSDP.println (" Sending Notify to 239.255.255.250:1900" );
162
+ if (_server) {
163
+ _server->unref ();
164
+ _server = 0 ;
165
+ }
166
+
167
+ _server = new UdpContext;
168
+ _server->ref ();
169
+
170
+ ip_addr_t ifaddr;
171
+ ifaddr.addr = WiFi.localIP ();
172
+ ip_addr_t multicast_addr;
173
+ multicast_addr.addr = (uint32_t ) SSDP_MULTICAST_ADDR;
174
+ if (igmp_joingroup (&ifaddr, &multicast_addr) != ERR_OK ) {
175
+ DEBUGV (" SSDP failed to join igmp group" );
176
+ return false ;
161
177
}
162
- #endif
163
178
164
- if (method == NONE){
165
- _server.beginPacket (_server.remoteIP (), _server.remotePort ());
166
- } else {
167
- _server.beginPacket (SSDP_MULTICAST_ADDR, SSDP_PORT);
179
+ if (!_server->listen (*IP_ADDR_ANY, SSDP_PORT)) {
180
+ return false ;
181
+ }
182
+
183
+ _server->setMulticastInterface (ifaddr);
184
+ _server->setMulticastTTL (SSDP_MULTICAST_TTL);
185
+ _server->onRx (std::bind (&SSDPClass::_update, this ));
186
+ if (!_server->connect (multicast_addr, SSDP_PORT)) {
187
+ return false ;
168
188
}
169
189
190
+ _startTimer ();
191
+
192
+ return true ;
193
+ }
194
+
195
+ void SSDPClass::_send (ssdp_method_t method){
196
+ char buffer[1460 ];
170
197
uint32_t ip = WiFi.localIP ();
171
198
172
- _server.printf (_ssdp_packet_template,
199
+ int len = snprintf (buffer, sizeof (buffer),
200
+ _ssdp_packet_template,
173
201
(method == NONE)?_ssdp_response_template:_ssdp_notify_template,
174
202
SSDP_INTERVAL,
175
203
_modelName, _modelNumber,
176
204
_uuid,
177
205
IP2STR (&ip), _port, _schemaURL
178
206
);
179
-
180
- _server.endPacket ();
207
+
208
+ _server->append (buffer, len);
209
+
210
+ ip_addr_t remoteAddr;
211
+ uint16_t remotePort;
212
+ if (method == NONE) {
213
+ remoteAddr.addr = _respondToAddr;
214
+ remotePort = _respondToPort;
215
+ #ifdef DEBUG_SSDP
216
+ DEBUG_SSDP.print (" Sending Response to " );
217
+ #endif
218
+ } else {
219
+ remoteAddr.addr = SSDP_MULTICAST_ADDR;
220
+ remotePort = SSDP_PORT;
221
+ #ifdef DEBUG_SSDP
222
+ DEBUG_SSDP.println (" Sending Notify to " );
223
+ #endif
224
+ }
225
+ #ifdef DEBUG_SSDP
226
+ DEBUG_SSDP.print (IPAddress (remoteAddr.addr ));
227
+ DEBUG_SSDP.print (" :" );
228
+ DEBUG_SSDP.println (remotePort);
229
+ #endif
230
+
231
+ _server->send (&remoteAddr, remotePort);
181
232
}
182
233
183
234
void SSDPClass::schema (WiFiClient client){
@@ -196,10 +247,13 @@ void SSDPClass::schema(WiFiClient client){
196
247
);
197
248
}
198
249
199
- uint8_t SSDPClass::update (){
200
- if (!_pending && _server. parsePacket () > 0 ) {
250
+ void SSDPClass::_update (){
251
+ if (!_pending && _server-> next ()) {
201
252
ssdp_method_t method = NONE;
202
253
254
+ _respondToAddr = _server->getRemoteAddress ();
255
+ _respondToPort = _server->getRemotePort ();
256
+
203
257
typedef enum {METHOD, URI, PROTO, KEY, VALUE, ABORT} states;
204
258
states state = METHOD;
205
259
@@ -211,8 +265,8 @@ uint8_t SSDPClass::update(){
211
265
212
266
char buffer[SSDP_BUFFER_SIZE] = {0 };
213
267
214
- while (_server. available () > 0 ){
215
- char c = _server. read ();
268
+ while (_server-> getSize () > 0 ){
269
+ char c = _server-> read ();
216
270
217
271
(c == ' \r ' || c == ' \n ' ) ? cr++ : cr = 0 ;
218
272
@@ -280,8 +334,6 @@ uint8_t SSDPClass::update(){
280
334
break ;
281
335
}
282
336
}
283
-
284
- _server.flush ();
285
337
}
286
338
287
339
if (_pending && (millis () - _process_time) > _delay){
@@ -291,6 +343,12 @@ uint8_t SSDPClass::update(){
291
343
_notify_time = millis ();
292
344
_send (NOTIFY);
293
345
}
346
+
347
+ if (_pending) {
348
+ while (_server->next ())
349
+ _server->flush ();
350
+ }
351
+
294
352
}
295
353
296
354
void SSDPClass::setSchemaURL (const char *url){
@@ -333,4 +391,16 @@ void SSDPClass::setManufacturerURL(const char *url){
333
391
strlcpy (_manufacturerURL, url, sizeof (_manufacturerURL));
334
392
}
335
393
394
+ void SSDPClass::_onTimerStatic (SSDPClass* self) {
395
+ self->_update ();
396
+ }
397
+
398
+ void SSDPClass::_startTimer () {
399
+ ETSTimer* tm = &(_timer->timer );
400
+ const int interval = 1000 ;
401
+ os_timer_disarm (tm);
402
+ os_timer_setfn (tm, reinterpret_cast <ETSTimerFunc*>(&SSDPClass::_onTimerStatic), reinterpret_cast <void *>(this ));
403
+ os_timer_arm (tm, interval, 1 /* repeat */ );
404
+ }
405
+
336
406
SSDPClass SSDP;
0 commit comments