Arduino DLNA Server
Schedule.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "DLNADevice.h"
4 #include "IUDPService.h"
5 
6 #define MAX_TMP_SIZE 300
7 #define ALIVE_MS 0
8 #define MAX_AGE (60 * 60 * 24)
9 
10 namespace tiny_dlna {
11 
12 
17 struct Schedule {
18  //int id = 0;
19  // scheduled next execution time
20  uint64_t time = 0;
21  // repeat every n ms
22  uint32_t repeat_ms = 0;
23  // repeat until;
24  uint64_t end_time = 0;
25  // schedle is active
26  bool active = false;
27 
28  virtual bool process(IUDPService &udp) { return false; }
29 
30  virtual const char *name() { return "n/a"; };
31 
32  operator bool() { return active; }
33 };
34 
39 class MSearchSchedule : public Schedule {
40  public:
41  MSearchSchedule(IPAddressAndPort addr, const char *searchTarget) {
42  address = addr;
43  search_target = searchTarget;
44  }
45  const char *name() override { return "MSearch"; }
46 
47  bool process(IUDPService &udp) override {
48  // we keep the data on the stack
49  DlnaLogger.log(DlnaDebug, "Sending %s for %s to %s", name(), search_target,
50  address.toString());
51 
52  char buffer[MAX_TMP_SIZE] = {0};
53  const char *tmp =
54  "M-SEARCH * HTTP/1.1\r\n"
55  "HOST: %s\r\n"
56  "MAN: \"ssdp:discover\"\r\n"
57  "MX: %d\r\n"
58  "ST: %s\r\n\r\n";
59  int n = snprintf(buffer, MAX_TMP_SIZE, tmp, address.toString(), max_age,
61  assert(n < MAX_TMP_SIZE);
62  DlnaLogger.log(DlnaDebug, "sending: %s", buffer);
63  udp.send(address, (uint8_t *)buffer, n);
64  return true;
65  }
66 
67  protected:
68  int max_age = 2;
70  const char *search_target = nullptr;
71 };
72 
78  public:
80  address = addr;
81  p_device = &device;
82  }
83  const char *name() override { return "MSearchReply"; }
84 
85  bool process(IUDPService &udp) override {
86  // we keep the data on the stack
87  DlnaLogger.log(DlnaInfo, "Sending %s for %s to %s", name(),
89 
90  DLNADevice &device = *p_device;
91  char buffer[MAX_TMP_SIZE] = {0};
92  const char *tmp =
93  "HTTP/1.1 200 OK\r\n"
94  "CACHE-CONTROL: max-age = %d\r\n"
95  "LOCATION: %s\r\n"
96  "ST: %s\r\n"
97  "USN: %s\r\n\r\n";
98  int n = snprintf(buffer, MAX_TMP_SIZE, tmp, max_age,
99  device.getDeviceURL().url(), search_target.c_str(),
100  device.getUDN());
101  assert(n < MAX_TMP_SIZE);
102  DlnaLogger.log(DlnaDebug, "sending: %s", buffer);
103  udp.send(address, (uint8_t *)buffer, n);
104  return true;
105  }
106 
110  int mx = 0;
111 
112  protected:
114 };
115 
121 class MSearchReplyCP : public Schedule {
122  public:
123  const char *name() override { return "MSearchReplyCP"; }
127 
128  bool process(IUDPService &udp) override {
129  DlnaLogger.log(DlnaInfo, "-> %s not processed", search_target.c_str());
130  return true;
131  }
132 
133 };
134 
136  public:
137  const char *name() override { return "NotifyReplyCP"; }
144 
145  // callback
146  std::function<bool(NotifyReplyCP &ref)> callback;
147 
148  bool process(IUDPService &udp) override {
149  if (callback(*this)){
150  DlnaLogger.log(DlnaInfo, "%s -> %s", name(), nts.c_str());
151  return true;
152  }
153 
154  DlnaLogger.log(DlnaInfo, "-> %s not processed", nts.c_str());
155  return true;
156  }
157 };
158 
163 class PostAliveSchedule : public Schedule {
164  public:
165  PostAliveSchedule(DLNADevice &device, uint32_t repeatMs) {
166  p_device = &device;
167  this->repeat_ms = repeatMs;
168  }
169  const char *name() override { return "PostAlive"; }
170 
171  void setRepeatMs(uint32_t ms) { this->repeat_ms = ms; }
172 
173  bool process(IUDPService &udp) override {
174  DlnaLogger.log(DlnaInfo, "Sending %s to %s", name(),
175  DLNABroadcastAddress.toString());
176  DLNADevice &device = *p_device;
177  char nt[100];
178  char usn[200];
179 
180  const char *device_url = device.getDeviceURL().url();
181  int max_age = 100;
182  // announce with udn
183  process(device.getUDN(), device.getUDN(), device_url, max_age, udp);
184  // NT: upnp:rootdevice\r\n
185  setupData("upnp:rootdevice", device.getUDN(), nt, usn);
186  process(nt, usn, device_url, max_age, udp);
187  // NT: urn:schemas-upnp-org:device:MediaRenderer:1\r\n
188  setupData(device.getDeviceType(), device.getUDN(), nt, usn);
189  process(nt, usn, device_url, max_age, udp);
190 
191  // announce with service udn
192  for (auto &service : device.getServices()) {
193  setupData(service.service_type, device.getUDN(), nt, usn);
194  process(nt, usn, device_url, max_age, udp);
195  }
196  return true;
197  }
198 
199  protected:
201  void setupData(const char *nt, const char *udn, char *result_nt,
202  char *result_usn) {
203  strcpy(result_nt, nt);
204  strcpy(result_usn, udn);
205  strcat(result_usn, "::");
206  strcat(result_usn, nt);
207  }
208 
209  bool process(const char *nt, const char *usn, const char *device_url,
210  int max_age, IUDPService &udp) {
211  // we keep the data on the stack
212  char buffer[MAX_TMP_SIZE] = {0};
213  const char *tmp =
214  "NOTIFY * HTTP/1.1\r\n"
215  "HOST:%s\r\n"
216  "CACHE-CONTROL: max-age = %d\r\n"
217  "LOCATION: %s\r\n"
218  "NT: %s\r\n"
219  "NTS: ssdp:alive\r\n"
220  "USN: %s\r\n\r\n";
221  int n = snprintf(buffer, MAX_TMP_SIZE, tmp, DLNABroadcastAddress.toString(),
222  max_age, device_url, nt, usn);
223 
224  assert(n < MAX_TMP_SIZE);
225  DlnaLogger.log(DlnaDebug, "sending: %s", buffer);
226  udp.send(DLNABroadcastAddress, (uint8_t *)buffer, n);
227  return true;
228  }
229 };
230 
235 class PostByeSchedule : public Schedule {
236  public:
237  PostByeSchedule(DLNADevice &device) { p_device = &device; }
238  const char *name() override { return "ByeBye"; }
239  bool process(IUDPService &udp) override {
240  DlnaLogger.log(DlnaInfo, "Sending %s to %s", name(),
241  DLNABroadcastAddress.toString());
242  // we keep the data on the stack
243  char buffer[MAX_TMP_SIZE] = {0};
244  const char *tmp =
245  "NOTIFY * HTTP/1.1\r\n"
246  "HOST: %s\r\n"
247  "CACHE-CONTROL: max-age = %d\r\n"
248  "LOCATION: *\r\n"
249  "NT: %s\r\n"
250  "NTS: ssdp:byebye\r\n"
251  "USN: %s\r\n\r\n";
252  int n = snprintf(buffer, MAX_TMP_SIZE, tmp, DLNABroadcastAddress.toString(),
254 
255  DlnaLogger.log(DlnaDebug, "sending: %s", buffer);
256  udp.send(DLNABroadcastAddress, (uint8_t *)buffer, n);
257  return true;
258  }
259 
260  protected:
261  int max_age = 120;
263 };
264 
269 class PostSubscribe : public Schedule {
270  public:
271  PostSubscribe(IPAddressAndPort address, const char *path, uint32_t sec) {
273  setDuration(sec);
274  }
275  const char *name() override { return "Subscribe"; }
276 
277  bool process(IUDPService &udp) override {
279  DlnaLogger.log(DlnaInfo, "Sending Subscribe to %s", address);
280 
281  char buffer[MAX_TMP_SIZE] = {0};
282  const char *tmp =
283  "SUBSCRIBE %s HTTP/1.1\r\n"
284  "HOST: %s\r\n"
285  "CALLBACK: %s"
286  "NT: upnp-event\r\n"
287  "TIMEOUT: Second-%d\r\n\r\n";
288  int n = snprintf(buffer, MAX_TMP_SIZE, tmp, path, address.toString(),
289  durationSec);
290  assert(n < MAX_TMP_SIZE);
291  DlnaLogger.log(DlnaDebug, "sending: %s", buffer);
292  udp.send(address, (uint8_t *)buffer, n);
293  return true;
294  }
295 
296  protected:
298  const char *path;
300 
302  this->address = address;
303  this->path = path;
304  }
305 
306  void setDuration(uint32_t sec) { durationSec = sec; }
307 };
308 
309 } // namespace tiny_dlna
#define MAX_TMP_SIZE
Definition: Schedule.h:6
#define MAX_AGE
Definition: Schedule.h:8
Device Attributes and generation of XML using urn:schemas-upnp-org:device-1-0. We could just return a...
Definition: DLNADevice.h:27
Vector< DLNAServiceInfo > & getServices()
Definition: DLNADevice.h:125
Url & getDeviceURL()
This method returns base url/device.xml.
Definition: DLNADevice.h:69
const char * getDeviceType()
Definition: DLNADevice.h:44
const char * getUDN()
Provide the udn uuid.
Definition: DLNADevice.h:50
Abstract Interface for UDP API.
Definition: IUDPService.h:34
virtual bool send(uint8_t *data, int len)=0
void log(DlnaLogLevel current_level, const char *fmt...)
Print log message.
Definition: Logger.h:40
Processing at control point to handle a MSearchReply from the device.
Definition: Schedule.h:121
Str usn
Definition: Schedule.h:125
const char * name() override
Definition: Schedule.h:123
Str location
Definition: Schedule.h:124
Str search_target
Definition: Schedule.h:126
bool process(IUDPService &udp) override
Definition: Schedule.h:128
Answer from device to MSearch request by sending a reply.
Definition: Schedule.h:77
MSearchReplySchedule(DLNADevice &device, IPAddressAndPort addr)
Definition: Schedule.h:79
Str search_target
Definition: Schedule.h:107
int mx
Definition: Schedule.h:110
bool process(IUDPService &udp) override
Definition: Schedule.h:85
const char * name() override
Definition: Schedule.h:83
IPAddressAndPort address
Definition: Schedule.h:108
DLNADevice * p_device
Definition: Schedule.h:109
int max_age
Definition: Schedule.h:113
Send MSearch request.
Definition: Schedule.h:39
IPAddressAndPort address
Definition: Schedule.h:69
const char * search_target
Definition: Schedule.h:70
MSearchSchedule(IPAddressAndPort addr, const char *searchTarget)
Definition: Schedule.h:41
const char * name() override
Definition: Schedule.h:45
bool process(IUDPService &udp) override
Definition: Schedule.h:47
int max_age
Definition: Schedule.h:68
Definition: Schedule.h:135
const char * name() override
Definition: Schedule.h:137
Str delivery_host_and_port
Definition: Schedule.h:139
std::function< bool(NotifyReplyCP &ref)> callback
Definition: Schedule.h:146
Str xml
Definition: Schedule.h:143
Str event_key
Definition: Schedule.h:142
Str subscription_id
Definition: Schedule.h:141
Str delivery_path
Definition: Schedule.h:140
bool process(IUDPService &udp) override
Definition: Schedule.h:148
Str nts
Definition: Schedule.h:138
Send out PostAlive messages: Repeated every 5 seconds.
Definition: Schedule.h:163
DLNADevice * p_device
Definition: Schedule.h:200
PostAliveSchedule(DLNADevice &device, uint32_t repeatMs)
Definition: Schedule.h:165
bool process(IUDPService &udp) override
Definition: Schedule.h:173
void setRepeatMs(uint32_t ms)
Definition: Schedule.h:171
bool process(const char *nt, const char *usn, const char *device_url, int max_age, IUDPService &udp)
Definition: Schedule.h:209
void setupData(const char *nt, const char *udn, char *result_nt, char *result_usn)
Definition: Schedule.h:201
const char * name() override
Definition: Schedule.h:169
Send out ByeBye message.
Definition: Schedule.h:235
PostByeSchedule(DLNADevice &device)
Definition: Schedule.h:237
DLNADevice * p_device
Definition: Schedule.h:262
bool process(IUDPService &udp) override
Definition: Schedule.h:239
int max_age
Definition: Schedule.h:261
const char * name() override
Definition: Schedule.h:238
Send SUBSCRIBE message via UDP unicast.
Definition: Schedule.h:269
void setDestination(IPAddressAndPort address, const char *path)
Definition: Schedule.h:301
void setDuration(uint32_t sec)
Definition: Schedule.h:306
IPAddressAndPort address
Definition: Schedule.h:297
const char * name() override
Definition: Schedule.h:275
const char * path
Definition: Schedule.h:298
int durationSec
Definition: Schedule.h:299
PostSubscribe(IPAddressAndPort address, const char *path, uint32_t sec)
Definition: Schedule.h:271
bool process(IUDPService &udp) override
Definition: Schedule.h:277
String implementation which keeps the data on the heap. We grow the allocated memory only if the copy...
Definition: Str.h:22
const char * c_str()
provides the string value as const char*
Definition: Str.h:188
const char * url()
Definition: Url.h:46
Definition: Allocator.h:6
@ DlnaDebug
Definition: Logger.h:16
@ DlnaInfo
Definition: Logger.h:16
LoggerClass DlnaLogger
Definition: Logger.cpp:5
IP Adress including Port information.
Definition: IPAddressAndPort.h:13
const char * toString()
Definition: IPAddressAndPort.h:19
An individual Schedule (to send out UDP messages)
Definition: Schedule.h:17
uint64_t end_time
Definition: Schedule.h:24
bool active
Definition: Schedule.h:26
virtual const char * name()
Definition: Schedule.h:30
virtual bool process(IUDPService &udp)
Definition: Schedule.h:28
uint64_t time
Definition: Schedule.h:20
uint32_t repeat_ms
Definition: Schedule.h:22