Arduino DLNA Server
DLNADeviceMgr.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "DLNADeviceMgr.h"
4 #include "DLNADevice.h"
6 #include "Schedule.h"
7 #include "basic/Url.h"
8 #include "http/HttpServer.h"
9 
10 namespace tiny_dlna {
11 
24  public:
26  bool begin(DLNADevice& device, IUDPService& udp, HttpServer& server) {
27  DlnaLogger.log(DlnaInfo, "DLNADevice::begin");
28 
29  p_server = &server;
30  p_udp = &udp;
31  setDevice(device);
32  setupParser();
33 
34  // check base url
35  Url baseUrl = device.getBaseURL();
36  DlnaLogger.log(DlnaInfo, "base URL: %s", baseUrl.url());
37 
38  if (StrView(device.getBaseURL().host()).equals("localhost")) {
39  DlnaLogger.log(DlnaError, "invalid base address: %s", baseUrl.url());
40  return false;
41  }
42 
43  // setup all services
45 
46  // setup web server
47  if (!setupDLNAServer(server)) {
48  DlnaLogger.log(DlnaError, "setupDLNAServer failed");
49  return false;
50  }
51 
52  // start web server
53  if (!p_server->begin(baseUrl.port())) {
54  DlnaLogger.log(DlnaError, "Server failed");
55  return false;
56  }
57 
58  // setup UDP
59  if (!p_udp->begin(DLNABroadcastAddress)) {
60  DlnaLogger.log(DlnaError, "UDP begin failed");
61  return false;
62  }
63 
64  if (!setupScheduler()) {
65  DlnaLogger.log(DlnaError, "Scheduler failed");
66  return false;
67  }
68 
69  is_active = true;
70  DlnaLogger.log(DlnaInfo, "Device successfully started");
71  return true;
72  }
73 
75  void end() {
76  p_server->end();
77 
78  // send 3 bye messages
80  bye->repeat_ms = 800;
81  scheduler.add(bye);
82 
83  // execute scheduler for 2 seconds
84  uint64_t end = millis() + 2000;
85  while (millis() < end) {
87  }
88 
89  is_active = false;
90  }
91 
93  bool loop() {
94  if (!is_active) return false;
95 
96  // handle server requests
97  bool rc = p_server->doLoop();
98  DlnaLogger.log(DlnaDebug, "server %s", rc ? "true" : "false");
99 
100  if (isSchedulerActive()) {
101  // process UDP requests
102  RequestData req = p_udp->receive();
103  if (req) {
104  Schedule* schedule = parser.parse(*p_device, req);
105  if (schedule != nullptr) {
106  scheduler.add(schedule);
107  }
108  }
109 
110  // execute scheduled udp replys
112  }
113 
114  // be nice, if we have other tasks
115  delay(5);
116 
117  return true;
118  }
119 
121  DLNAServiceInfo getService(const char* id) {
122  return p_device->getService(id);
123  }
124 
126  DLNADevice& getDevice() { return *p_device; }
127 
129  void setSchedulerActive(bool flag) { scheduler_active = flag; }
130 
133 
136  void setPostAliveRepeatMs(uint32_t ms) { post_alive_repeat_ms = ms; }
137 
138  protected:
141  IUDPService* p_udp = nullptr;
142  DLNADevice* p_device = nullptr;
143  HttpServer* p_server = nullptr;
144  bool is_active = false;
145  bool scheduler_active = true;
146  uint32_t post_alive_repeat_ms = 0;
147 
148  void setDevice(DLNADevice& device) { p_device = &device; }
149 
152  bool setupParser() {
153  parser.addMSearchST("upnp:rootdevice");
154  parser.addMSearchST("ssdp:all");
157  return true;
158  }
159 
161  bool setupScheduler() {
162  // schedule post alive messages: Usually repeated 2 times (because UDP
163  // messages might be lost)
164  PostAliveSchedule* postAlive =
166  PostAliveSchedule* postAlive1 =
168  postAlive1->time = millis() + 100;
169  scheduler.add(postAlive);
170  scheduler.add(postAlive1);
171  return true;
172  }
173 
175  virtual bool setupDLNAServer(HttpServer& srv) {
176  char buffer[DLNA_MAX_URL_LEN] = {0};
177  StrView url(buffer, DLNA_MAX_URL_LEN);
178 
179  // add device url to server
180  const char* device_path = p_device->getDeviceURL().path();
181  const char* prefix = p_device->getBaseURL().path();
182 
183  DlnaLogger.log(DlnaInfo, "Setting up device path: %s", device_path);
184  void* ref[] = {p_device};
185 
186  if (!StrView(device_path).isEmpty()) {
187  p_server->rewrite("/", device_path);
188  p_server->rewrite("/dlna/device.xml", device_path);
189  p_server->rewrite("/index.html", device_path);
190  p_server->on(device_path, T_GET, deviceXMLCallback, ref, 1);
191  }
192 
193  // Register icon and privide favicon.ico
194  Icon icon = p_device->getIcon();
195  if (icon.icon_data != nullptr) {
196  char tmp[DLNA_MAX_URL_LEN];
197  const char* icon_path = url.buildPath(prefix, icon.icon_url);
198  p_server->on(icon_path, T_GET, icon.mime, (const uint8_t*)icon.icon_data,
199  icon.icon_size);
200  p_server->on("/favicon.ico", T_GET, icon.mime,
201  (const uint8_t*)icon.icon_data, icon.icon_size);
202  }
203 
204  // Register Service URLs
205  for (DLNAServiceInfo& service : p_device->getServices()) {
206  p_server->on(url.buildPath(prefix, service.scpd_url), T_GET,
207  service.scp_cb, ref, 1);
208  p_server->on(url.buildPath(prefix, service.control_url), T_POST,
209  service.control_cb, ref, 1);
210  p_server->on(url.buildPath(prefix, service.event_sub_url), T_GET,
211  service.event_sub_cb, ref, 1);
212  }
213 
214  return true;
215  }
216 
218  static void deviceXMLCallback(HttpServer* server, const char* requestPath,
220  DLNADevice* device_xml = (DLNADevice*)(hl->context[0]);
221  assert(device_xml != nullptr);
222  if (device_xml != nullptr) {
223  Client& client = server->client();
224  assert(&client != nullptr);
225  DlnaLogger.log(DlnaInfo, "reply %s", "DeviceXML");
226  server->replyHeader().setValues(200, "SUCCESS");
227  server->replyHeader().put(CONTENT_TYPE, "text/xml");
229  server->replyHeader().write(client);
230 
231  // print xml result
232  device_xml->print(client);
233  server->endClient();
234  } else {
235  DlnaLogger.log(DlnaError, "DLNADevice is null");
236  server->replyNotFound();
237  }
238  }
239 
243  virtual void setupServices(DLNADevice& deviceInfo) {};
244 };
245 
246 } // namespace tiny_dlna
#define DLNA_MAX_URL_LEN
Definition: DLNAServiceInfo.h:5
Setup of a Basic DLNA Device service. The device registers itself to the network and answers to the D...
Definition: DLNADeviceMgr.h:23
uint32_t post_alive_repeat_ms
Definition: DLNADeviceMgr.h:146
void setDevice(DLNADevice &device)
Definition: DLNADeviceMgr.h:148
DLNADevice * p_device
Definition: DLNADeviceMgr.h:142
bool is_active
Definition: DLNADeviceMgr.h:144
bool setupParser()
Definition: DLNADeviceMgr.h:152
bool isSchedulerActive()
Checks if the scheduler is active.
Definition: DLNADeviceMgr.h:132
DLNAServiceInfo getService(const char *id)
Provide addess to the service information.
Definition: DLNADeviceMgr.h:121
bool scheduler_active
Definition: DLNADeviceMgr.h:145
static void deviceXMLCallback(HttpServer *server, const char *requestPath, HttpRequestHandlerLine *hl)
callback to provide device XML
Definition: DLNADeviceMgr.h:218
virtual bool setupDLNAServer(HttpServer &srv)
set up Web Server to handle Service Addresses
Definition: DLNADeviceMgr.h:175
bool setupScheduler()
Schedule PostAlive messages.
Definition: DLNADeviceMgr.h:161
bool loop()
call this method in the Arduino loop as often as possible
Definition: DLNADeviceMgr.h:93
bool begin(DLNADevice &device, IUDPService &udp, HttpServer &server)
start the
Definition: DLNADeviceMgr.h:26
void setPostAliveRepeatMs(uint32_t ms)
Definition: DLNADeviceMgr.h:136
HttpServer * p_server
Definition: DLNADeviceMgr.h:143
void setSchedulerActive(bool flag)
We can activate/deactivate the scheduler.
Definition: DLNADeviceMgr.h:129
DLNADeviceRequestParser parser
Definition: DLNADeviceMgr.h:140
void end()
Stops the processing and releases the resources.
Definition: DLNADeviceMgr.h:75
virtual void setupServices(DLNADevice &deviceInfo)
Definition: DLNADeviceMgr.h:243
Scheduler scheduler
Definition: DLNADeviceMgr.h:139
IUDPService * p_udp
Definition: DLNADeviceMgr.h:141
DLNADevice & getDevice()
Provides the device.
Definition: DLNADeviceMgr.h:126
Translates DLNA UDP Requests to Schedule so that we can schedule a reply.
Definition: DLNADeviceRequestParser.h:15
Schedule * parse(DLNADevice &device, RequestData &req)
Definition: DLNADeviceRequestParser.h:20
void addMSearchST(const char *accept)
Definition: DLNADeviceRequestParser.h:18
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
DLNAServiceInfo & getService(const char *id)
Finds a service definition by name.
Definition: DLNADevice.h:115
Url & getDeviceURL()
This method returns base url/device.xml.
Definition: DLNADevice.h:69
void print(Print &out)
renderes the device xml
Definition: DLNADevice.h:34
Url & getBaseURL()
Provides the base url.
Definition: DLNADevice.h:56
const char * getDeviceType()
Definition: DLNADevice.h:44
Icon getIcon(int idx=0)
Definition: DLNADevice.h:146
const char * getUDN()
Provide the udn uuid.
Definition: DLNADevice.h:50
Attributes needed for the DLNA Service Definition.
Definition: DLNAServiceInfo.h:16
HttpHeader & put(const char *key, const char *value)
Definition: HttpHeader.h:102
void write(Client &out)
Definition: HttpHeader.h:266
void setValues(int statusCode, const char *msg="", const char *protocol=nullptr)
Definition: HttpHeader.h:414
Used to register and process callbacks.
Definition: HttpRequestHandlerLine.h:19
void ** context
Definition: HttpRequestHandlerLine.h:39
A Simple Header only implementation of Http Server that allows the registration of callback functions...
Definition: HttpServer.h:24
Client & client()
Provides the current client.
Definition: HttpServer.h:436
bool begin(int port, const char *ssid, const char *password)
Definition: HttpServer.h:49
bool doLoop()
Legacy method: same as copy();.
Definition: HttpServer.h:404
void on(const char *url, TinyMethodID method, web_callback_fn fn, void *ctx[]=nullptr, int ctxCount=0)
register a generic handler
Definition: HttpServer.h:89
void endClient()
closes the connection to the current client_ptr
Definition: HttpServer.h:386
void end()
stops the server_ptr
Definition: HttpServer.h:76
void replyNotFound()
write 404 reply
Definition: HttpServer.h:366
void rewrite(const char *from, const char *to)
adds a rewrite rule
Definition: HttpServer.h:82
HttpReplyHeader & replyHeader()
provides the reply header
Definition: HttpServer.h:383
Abstract Interface for UDP API.
Definition: IUDPService.h:34
virtual RequestData receive()=0
virtual bool begin(IPAddressAndPort addr)=0
Information about the icon.
Definition: Icon.h:10
const char * icon_url
Definition: Icon.h:16
int icon_size
Definition: Icon.h:18
const char * mime
Definition: Icon.h:12
uint8_t * icon_data
Definition: Icon.h:17
void log(DlnaLogLevel current_level, const char *fmt...)
Print log message.
Definition: Logger.h:40
Send out PostAlive messages: Repeated every 5 seconds.
Definition: Schedule.h:163
Send out ByeBye message.
Definition: Schedule.h:235
Scheduler which processes all due Schedules (to send out UDP replies)
Definition: Scheduler.h:15
void execute(IUDPService &udp)
Execute all due schedules.
Definition: Scheduler.h:25
void add(Schedule *schedule)
Add a schedule to the scheduler.
Definition: Scheduler.h:18
A simple wrapper to provide string functions on char*. If the underlying char* is a const we do not a...
Definition: StrView.h:25
const char * buildPath(const char *start, const char *p1=nullptr, const char *p2=nullptr)
Definition: StrView.h:736
virtual bool equals(const char *str)
checks if the string equals indicated parameter string
Definition: StrView.h:171
URL parser which breaks a full url string up into its individual parts.
Definition: Url.h:18
const char * path()
Definition: Url.h:47
int port()
Definition: Url.h:51
const char * url()
Definition: Url.h:46
const char * host()
Definition: Url.h:48
Definition: Allocator.h:6
const char * CONTENT_TYPE
Definition: HttpHeader.h:16
const char * CON_KEEP_ALIVE
Definition: HttpHeader.h:20
@ DlnaDebug
Definition: Logger.h:16
@ DlnaInfo
Definition: Logger.h:16
@ DlnaError
Definition: Logger.h:16
@ T_GET
Definition: HttpHeader.h:37
@ T_POST
Definition: HttpHeader.h:39
LoggerClass DlnaLogger
Definition: Logger.cpp:5
const char * CONNECTION
Definition: HttpHeader.h:18
Provides information of the received UDP which consists of the (xml) data and the peer address and po...
Definition: IUDPService.h:23
An individual Schedule (to send out UDP messages)
Definition: Schedule.h:17
uint64_t time
Definition: Schedule.h:20
uint32_t repeat_ms
Definition: Schedule.h:22