Arduino DLNA Server
Loading...
Searching...
No Matches
Schedule.h
Go to the documentation of this file.
1#pragma once
2
6
7#define MAX_TMP_SIZE 300
8#define ALIVE_MS 0
9#define MAX_AGE (60 * 60 * 24)
10
11namespace tiny_dlna {
12
13
18struct Schedule {
19 //int id = 0;
20 // scheduled next execution time
21 uint64_t time = 0;
22 // repeat every n ms
23 uint32_t repeat_ms = 0;
24 // repeat until;
25 uint64_t end_time = 0;
26 // schedle is active
27 bool active = false;
28 // optional address associated with the schedule (e.g. requester)
30 // enables logging the address when the schedule is queued
31 bool report_ip = false;
32
33 virtual bool process(IUDPService &udp) { return false; }
34
35 virtual const char *name() { return "n/a"; };
36
37 virtual bool isValid() { return true; }
38
39 operator bool() { return active; }
40};
41
46class MSearchSchedule : public Schedule {
47 public:
48 MSearchSchedule(IPAddressAndPort addr, const char *searchTarget, int mx = 3) {
49 this->address = addr;
50 search_target = searchTarget;
51 max_age = mx;
52 }
53 const char *name() override { return "MSearch"; }
54
55 bool process(IUDPService &udp) override {
56 // we keep the data on the stack
57 DlnaLogger.log(DlnaLogLevel::Debug, "Sending %s for %s to %s", name(), search_target,
59
60 char buffer[MAX_TMP_SIZE] = {0};
61 const char *tmp =
62 "M-SEARCH * HTTP/1.1\r\n"
63 "HOST: %s\r\n"
64 "MAN: \"ssdp:discover\"\r\n"
65 "MX: %d\r\n"
66 "ST: %s\r\n\r\n";
67 int n = snprintf(buffer, MAX_TMP_SIZE, tmp, address.toString(), max_age,
69 assert(n < MAX_TMP_SIZE);
70 DlnaLogger.log(DlnaLogLevel::Debug, "sending: %s", buffer);
71 udp.send(address, (uint8_t *)buffer, n);
72 return true;
73 }
74
75 protected:
76 int max_age = 3;
77 const char *search_target = nullptr;
78};
79
85 public:
87 this->address = addr;
88 this->report_ip = true;
89 p_device = &device;
90 }
91 const char *name() override { return "MSearchReply"; }
92
93 bool process(IUDPService &udp) override {
94 // we keep the data on the stack
95 DlnaLogger.log(DlnaLogLevel::Debug, "Sending %s for %s to %s", name(),
97
98 DLNADeviceInfo &device = *p_device;
99 char buffer[MAX_TMP_SIZE] = {0};
100 const char *tmp =
101 "HTTP/1.1 200 OK\r\n"
102 "CACHE-CONTROL: max-age = %d\r\n"
103 "LOCATION: %s\r\n"
104 "ST: %s\r\n"
105 "USN: %s\r\n\r\n";
106 int n = snprintf(buffer, MAX_TMP_SIZE, tmp, max_age,
107 device.getDeviceURL().url(), search_target.c_str(),
108 device.getUDN());
109 assert(n < MAX_TMP_SIZE);
110 DlnaLogger.log(DlnaLogLevel::Debug, "sending: %s", buffer);
111 udp.send(address, (uint8_t *)buffer, n);
112 return true;
113 }
114
115 bool isValid() override {
116 // Check if the requester's IP is on the same subnet as defined by DLNA_DISCOVERY_NETMASK
117 IPAddress netmask = DLNA_DISCOVERY_NETMASK;
118 IPAddress localIP = p_device->getIPAddress();
119 IPAddress peerIP = address.address;
120 Str netmask_str = netmask.toString().c_str();
121 Str localIP_str = localIP.toString().c_str();
122
123 // Apply netmask to both local and peer IP addresses
124 for (int i = 0; i < 4; i++) {
125 if ((localIP[i] & netmask[i]) != (peerIP[i] & netmask[i])) {
126 DlnaLogger.log(DlnaLogLevel::Info,
127 "Discovery request from %s filtered (not in same subnet as %s with mask %s)",
128 address.toString(), localIP_str.c_str(), netmask_str.c_str());
129 return false;
130 }
131 }
132 return true;
133 }
134
137 int mx = 0;
138
139 protected:
141};
142
148class MSearchReplyCP : public Schedule {
149 public:
150 const char *name() override { return "MSearchReplyCP"; }
154
155 bool process(IUDPService &udp) override {
156 DlnaLogger.log(DlnaLogLevel::Debug, "-> %s not processed", search_target.c_str());
157 return true;
158 }
159
160};
161
190 public:
191 const char *name() override { return "NotifyReplyCP"; }
192 Str nts{80};
198
199 // callback invoked by the scheduler when processing this notification.
200 // Return true if the notification was handled; false otherwise.
201 std::function<bool(NotifyReplyCP &ref)> callback;
202
203 bool process(IUDPService &udp) override {
204 if (callback(*this)){
205 DlnaLogger.log(DlnaLogLevel::Debug, "%s -> %s", name(), nts.c_str());
206 return true;
207 }
208
209 DlnaLogger.log(DlnaLogLevel::Debug, "-> %s not processed", nts.c_str());
210 return true;
211 }
212};
213
219 public:
220 PostAliveSchedule(DLNADeviceInfo &device, uint32_t repeatMs) {
221 p_device = &device;
222 this->repeat_ms = repeatMs;
223 }
224 const char *name() override { return "PostAlive"; }
225
226 void setRepeatMs(uint32_t ms) { this->repeat_ms = ms; }
227
228 bool process(IUDPService &udp) override {
229 DlnaLogger.log(DlnaLogLevel::Debug, "Sending %s to %s", name(),
230 DLNABroadcastAddress.toString());
231 DLNADeviceInfo &device = *p_device;
232 char nt[100];
233 char usn[200];
234
235 const char *device_url = device.getDeviceURL().url();
236 int max_age = 100;
237 // announce with udn
238 process(device.getUDN(), device.getUDN(), device_url, max_age, udp);
239 // NT: upnp:rootdevice\r\n
240 setupData("upnp:rootdevice", device.getUDN(), nt, usn);
241 process(nt, usn, device_url, max_age, udp);
242 // NT: urn:schemas-upnp-org:device:MediaRenderer:1\r\n
243 setupData(device.getDeviceType(), device.getUDN(), nt, usn);
244 process(nt, usn, device_url, max_age, udp);
245
246 // announce with service udn
247 for (auto &service : device.getServices()) {
248 setupData(service.service_type, device.getUDN(), nt, usn);
249 process(nt, usn, device_url, max_age, udp);
250 }
251 return true;
252 }
253
254 protected:
256 void setupData(const char *nt, const char *udn, char *result_nt,
257 char *result_usn) {
258 strcpy(result_nt, nt);
259 strcpy(result_usn, udn);
260 strcat(result_usn, "::");
261 strcat(result_usn, nt);
262 }
263
264 bool process(const char *nt, const char *usn, const char *device_url,
265 int max_age, IUDPService &udp) {
266 // we keep the data on the stack
267 char buffer[MAX_TMP_SIZE] = {0};
268 const char *tmp =
269 "NOTIFY * HTTP/1.1\r\n"
270 "HOST:%s\r\n"
271 "CACHE-CONTROL: max-age = %d\r\n"
272 "LOCATION: %s\r\n"
273 "NT: %s\r\n"
274 "NTS: ssdp:alive\r\n"
275 "USN: %s\r\n\r\n";
276 int n = snprintf(buffer, MAX_TMP_SIZE, tmp, DLNABroadcastAddress.toString(),
277 max_age, device_url, nt, usn);
278
279 assert(n < MAX_TMP_SIZE);
280 DlnaLogger.log(DlnaLogLevel::Debug, "sending: %s", buffer);
281 udp.send(DLNABroadcastAddress, (uint8_t *)buffer, n);
282 return true;
283 }
284};
285
290class PostByeSchedule : public Schedule {
291 public:
293 const char *name() override { return "ByeBye"; }
294 bool process(IUDPService &udp) override {
295 DlnaLogger.log(DlnaLogLevel::Debug, "Sending %s to %s", name(),
296 DLNABroadcastAddress.toString());
297 // we keep the data on the stack
298 char buffer[MAX_TMP_SIZE] = {0};
299 const char *tmp =
300 "NOTIFY * HTTP/1.1\r\n"
301 "HOST: %s\r\n"
302 "CACHE-CONTROL: max-age = %d\r\n"
303 "LOCATION: *\r\n"
304 "NT: %s\r\n"
305 "NTS: ssdp:byebye\r\n"
306 "USN: %s\r\n\r\n";
307 int n = snprintf(buffer, MAX_TMP_SIZE, tmp, DLNABroadcastAddress.toString(),
309
310 DlnaLogger.log(DlnaLogLevel::Debug, "sending: %s", buffer);
311 udp.send(DLNABroadcastAddress, (uint8_t *)buffer, n);
312 return true;
313 }
314
315 protected:
316 int max_age = 1800;
318};
319
324class PostSubscribe : public Schedule {
325 public:
326 PostSubscribe(IPAddressAndPort addr, const char *path, uint32_t sec) {
327 setDestination(addr, path);
328 setDuration(sec);
329 }
330 const char *name() override { return "Subscribe"; }
331
332 bool process(IUDPService &udp) override {
334 DlnaLogger.log(DlnaLogLevel::Debug, "Sending Subscribe to %s", address.toString());
335
336 char buffer[MAX_TMP_SIZE] = {0};
337 const char *tmp =
338 "SUBSCRIBE %s HTTP/1.1\r\n"
339 "HOST: %s\r\n"
340 "CALLBACK: %s"
341 "NT: upnp-event\r\n"
342 "TIMEOUT: Second-%d\r\n\r\n";
343 int n = snprintf(buffer, MAX_TMP_SIZE, tmp, path, address.toString(),
345 assert(n < MAX_TMP_SIZE);
346 DlnaLogger.log(DlnaLogLevel::Debug, "sending: %s", buffer);
347 udp.send(address, (uint8_t *)buffer, n);
348 return true;
349 }
350
351 protected:
352 const char *path;
353 int durationSec = 0;
354
355 void setDestination(IPAddressAndPort addr, const char *path) {
356 this->address = addr;
357 this->path = path;
358 }
359
360 void setDuration(uint32_t sec) { durationSec = sec; }
361};
362
363} // namespace tiny_dlna
#define MAX_TMP_SIZE
Definition: Schedule.h:7
#define MAX_AGE
Definition: Schedule.h:9
Device Attributes and generation of XML using urn:schemas-upnp-org:device-1-0. We could just return a...
Definition: DLNADeviceInfo.h:25
Vector< DLNAServiceInfo > & getServices()
Provides all service definitions.
Definition: DLNADeviceInfo.h:203
const char * getUDN()
Provide the udn uuid.
Definition: DLNADeviceInfo.h:88
Url & getDeviceURL()
This method returns base url/device.xml.
Definition: DLNADeviceInfo.h:129
IPAddress getIPAddress()
Provides the local IP address.
Definition: DLNADeviceInfo.h:144
const char * getDeviceType()
Definition: DLNADeviceInfo.h:82
Abstract Interface for UDP API.
Definition: IUDPService.h:33
virtual bool send(uint8_t *data, int len)=0
Send data to the default destination.
Processing at control point to handle a MSearchReply from the device.
Definition: Schedule.h:148
Str usn
Definition: Schedule.h:152
const char * name() override
Definition: Schedule.h:150
Str location
Definition: Schedule.h:151
Str search_target
Definition: Schedule.h:153
bool process(IUDPService &udp) override
Definition: Schedule.h:155
Answer from device to MSearch request by sending a reply.
Definition: Schedule.h:84
Str search_target
Definition: Schedule.h:135
bool isValid() override
Definition: Schedule.h:115
int mx
Definition: Schedule.h:137
bool process(IUDPService &udp) override
Definition: Schedule.h:93
MSearchReplySchedule(DLNADeviceInfo &device, IPAddressAndPort addr)
Definition: Schedule.h:86
DLNADeviceInfo * p_device
Definition: Schedule.h:136
const char * name() override
Definition: Schedule.h:91
int max_age
Definition: Schedule.h:140
Send MSearch request.
Definition: Schedule.h:46
const char * search_target
Definition: Schedule.h:77
bool process(IUDPService &udp) override
Definition: Schedule.h:55
const char * name() override
Definition: Schedule.h:53
MSearchSchedule(IPAddressAndPort addr, const char *searchTarget, int mx=3)
Definition: Schedule.h:48
int max_age
Definition: Schedule.h:76
Represents a notification/notify reply scheduled for control-point processing.
Definition: Schedule.h:189
Str delivery_host_and_port
Definition: Schedule.h:193
std::function< bool(NotifyReplyCP &ref)> callback
Definition: Schedule.h:201
Str xml
Definition: Schedule.h:197
Str event_key
Definition: Schedule.h:196
Str subscription_id
Definition: Schedule.h:195
Str delivery_path
Definition: Schedule.h:194
const char * name() override
Definition: Schedule.h:191
bool process(IUDPService &udp) override
Definition: Schedule.h:203
Str nts
Definition: Schedule.h:192
Send out PostAlive messages: Repeated every 5 seconds.
Definition: Schedule.h:218
DLNADeviceInfo * p_device
Definition: Schedule.h:255
PostAliveSchedule(DLNADeviceInfo &device, uint32_t repeatMs)
Definition: Schedule.h:220
const char * name() override
Definition: Schedule.h:224
bool process(IUDPService &udp) override
Definition: Schedule.h:228
void setRepeatMs(uint32_t ms)
Definition: Schedule.h:226
bool process(const char *nt, const char *usn, const char *device_url, int max_age, IUDPService &udp)
Definition: Schedule.h:264
void setupData(const char *nt, const char *udn, char *result_nt, char *result_usn)
Definition: Schedule.h:256
Send out ByeBye message.
Definition: Schedule.h:290
DLNADeviceInfo * p_device
Definition: Schedule.h:317
PostByeSchedule(DLNADeviceInfo &device)
Definition: Schedule.h:292
bool process(IUDPService &udp) override
Definition: Schedule.h:294
int max_age
Definition: Schedule.h:316
const char * name() override
Definition: Schedule.h:293
Send SUBSCRIBE message via UDP unicast.
Definition: Schedule.h:324
const char * name() override
Definition: Schedule.h:330
void setDuration(uint32_t sec)
Definition: Schedule.h:360
void setDestination(IPAddressAndPort addr, const char *path)
Definition: Schedule.h:355
PostSubscribe(IPAddressAndPort addr, const char *path, uint32_t sec)
Definition: Schedule.h:326
const char * path
Definition: Schedule.h:352
int durationSec
Definition: Schedule.h:353
bool process(IUDPService &udp) override
Definition: Schedule.h:332
Heap-backed string utility used throughout tiny_dlna.
Definition: Str.h:27
const char * c_str() const
C-string pointer to internal buffer.
Definition: Str.h:88
const char * url()
Definition: Url.h:39
#define DLNA_DISCOVERY_NETMASK
Define the netmask for discovery filtering.
Definition: dlna_config.h:187
Definition: Allocator.h:13
IP Adress including Port information.
Definition: IPAddressAndPort.h:20
const char * toString()
Definition: IPAddressAndPort.h:26
IPAddress address
Definition: IPAddressAndPort.h:23
An individual Schedule (to send out UDP messages)
Definition: Schedule.h:18
uint64_t end_time
Definition: Schedule.h:25
IPAddressAndPort address
Definition: Schedule.h:29
bool active
Definition: Schedule.h:27
bool report_ip
Definition: Schedule.h:31
virtual const char * name()
Definition: Schedule.h:35
virtual bool isValid()
Definition: Schedule.h:37
virtual bool process(IUDPService &udp)
Definition: Schedule.h:33
uint64_t time
Definition: Schedule.h:21
uint32_t repeat_ms
Definition: Schedule.h:23