Arduino DLNA Server
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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  const char* baseUrl = device.getBaseURL();
36  DlnaLogger.log(DlnaInfo, "base URL: %s", baseUrl);
37 
38  if (StrView(device.getBaseURL()).contains("localhost")) {
39  DlnaLogger.log(DlnaError, "invalid base address: %s", baseUrl);
40  return false;
41  }
42 
43  // setup all services
45  device.setupServices(server, udp);
46 
47  // setup web server
48  if (!setupDLNAServer(server)) {
49  DlnaLogger.log(DlnaError, "setupDLNAServer failed");
50  return false;
51  }
52 
53  // start web server
54  Url url{baseUrl};
55  if (!p_server->begin(url.port())) {
56  DlnaLogger.log(DlnaError, "Server failed");
57  return false;
58  }
59 
60  // setup UDP
61  if (!p_udp->begin(DLNABroadcastAddress)) {
62  DlnaLogger.log(DlnaError, "UDP begin failed");
63  return false;
64  }
65 
66  if (!setupScheduler()) {
67  DlnaLogger.log(DlnaError, "Scheduler failed");
68  return false;
69  }
70 
71  is_active = true;
72  DlnaLogger.log(DlnaInfo, "Device successfully started");
73  return true;
74  }
75 
77  void end() {
78  p_server->end();
79 
80  // send 3 bye messages
82  bye->repeat_ms = 800;
83  scheduler.add(bye);
84 
85  // execute scheduler for 2 seconds
86  uint64_t end = millis() + 2000;
87  while (millis() < end) {
89  }
90 
91  is_active = false;
92  }
93 
95  bool loop() {
96  if (!is_active) return false;
97 
98  // handle server requests
99  bool rc = p_server->doLoop();
100  DlnaLogger.log(DlnaDebug, "server %s", rc ? "true" : "false");
101 
102  if (isSchedulerActive()) {
103  // process UDP requests
104  RequestData req = p_udp->receive();
105  if (req) {
106  Schedule* schedule = parser.parse(*p_device, req);
107  if (schedule != nullptr) {
108  scheduler.add(schedule);
109  }
110  }
111 
112  // execute scheduled udp replys
114  }
115 
116  // be nice, if we have other tasks
117  p_device->loop();
118 
119  return true;
120  }
121 
123  DLNAServiceInfo getService(const char* id) {
124  return p_device->getService(id);
125  }
126 
128  DLNADevice& getDevice() { return *p_device; }
129 
131  void setSchedulerActive(bool flag) { scheduler_active = flag; }
132 
135 
138  void setPostAliveRepeatMs(uint32_t ms) { post_alive_repeat_ms = ms; }
139 
140  protected:
143  IUDPService* p_udp = nullptr;
144  DLNADevice* p_device = nullptr;
145  HttpServer* p_server = nullptr;
146  bool is_active = false;
147  bool scheduler_active = true;
148  uint32_t post_alive_repeat_ms = 0;
149 
150  void setDevice(DLNADevice& device) { p_device = &device; }
151 
154  bool setupParser() {
155  parser.addMSearchST("upnp:rootdevice");
156  parser.addMSearchST("ssdp:all");
159  return true;
160  }
161 
163  bool setupScheduler() {
164  // schedule post alive messages: Usually repeated 2 times (because UDP
165  // messages might be lost)
166  PostAliveSchedule* postAlive =
168  PostAliveSchedule* postAlive1 =
170  postAlive1->time = millis() + 100;
171  scheduler.add(postAlive);
172  scheduler.add(postAlive1);
173  return true;
174  }
175 
177  virtual bool setupDLNAServer(HttpServer& srv) {
178  char buffer[DLNA_MAX_URL_LEN] = {0};
179  StrView url(buffer, DLNA_MAX_URL_LEN);
180 
181  // add device url to server
182  const char* device_path = p_device->getDeviceURL().path();
183  const char* prefix = p_device->getBaseURL();
184 
185  DlnaLogger.log(DlnaInfo, "Setting up device path: %s", device_path);
186  void* ref[] = {p_device};
187 
188  if (!StrView(device_path).isEmpty()) {
189  p_server->rewrite("/", device_path);
190  p_server->rewrite("/dlna/device.xml", device_path);
191  p_server->rewrite("/index.html", device_path);
192  p_server->on(device_path, T_GET, deviceXMLCallback, ref, 1);
193  }
194 
195  // Register icon and privide favicon.ico
196  Icon icon = p_device->getIcon();
197  if (icon.icon_data != nullptr) {
198  char tmp[DLNA_MAX_URL_LEN];
199  const char* icon_path = url.buildPath(prefix, icon.icon_url);
200  p_server->on(icon_path, T_GET, icon.mime, (const uint8_t*)icon.icon_data,
201  icon.icon_size);
202  p_server->on("/favicon.ico", T_GET, icon.mime,
203  (const uint8_t*)icon.icon_data, icon.icon_size);
204  }
205 
206  // Register Service URLs
207  for (DLNAServiceInfo& service : p_device->getServices()) {
208  p_server->on(url.buildPath(prefix, service.scpd_url), T_GET,
209  service.scp_cb, ref, 1);
210  p_server->on(url.buildPath(prefix, service.control_url), T_POST,
211  service.control_cb, ref, 1);
212  p_server->on(url.buildPath(prefix, service.event_sub_url), T_GET,
213  service.event_sub_cb, ref, 1);
214  }
215 
216  return true;
217  }
218 
220  static void deviceXMLCallback(HttpServer* server, const char* requestPath,
222  DLNADevice* device_xml = (DLNADevice*)(hl->context[0]);
223  assert(device_xml != nullptr);
224  if (device_xml != nullptr) {
225  Client& client = server->client();
226  assert(&client != nullptr);
227  DlnaLogger.log(DlnaInfo, "reply %s", "DeviceXML");
228  server->replyHeader().setValues(200, "SUCCESS");
229  server->replyHeader().put(CONTENT_TYPE, "text/xml");
231  server->replyHeader().write(client);
232 
233  // print xml result
234  device_xml->print(client);
235  server->endClient();
236  } else {
237  DlnaLogger.log(DlnaError, "DLNADevice is null");
238  server->replyNotFound();
239  }
240  }
241 
245  virtual void setupServices(DLNADevice& deviceInfo) {};
246 };
247 
248 } // 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:148
void setDevice(DLNADevice &device)
Definition: DLNADeviceMgr.h:150
DLNADevice * p_device
Definition: DLNADeviceMgr.h:144
bool is_active
Definition: DLNADeviceMgr.h:146
bool setupParser()
Definition: DLNADeviceMgr.h:154
bool isSchedulerActive()
Checks if the scheduler is active.
Definition: DLNADeviceMgr.h:134
DLNAServiceInfo getService(const char *id)
Provide addess to the service information.
Definition: DLNADeviceMgr.h:123
bool scheduler_active
Definition: DLNADeviceMgr.h:147
static void deviceXMLCallback(HttpServer *server, const char *requestPath, HttpRequestHandlerLine *hl)
callback to provide device XML
Definition: DLNADeviceMgr.h:220
virtual bool setupDLNAServer(HttpServer &srv)
set up Web Server to handle Service Addresses
Definition: DLNADeviceMgr.h:177
bool setupScheduler()
Schedule PostAlive messages.
Definition: DLNADeviceMgr.h:163
bool loop()
call this method in the Arduino loop as often as possible
Definition: DLNADeviceMgr.h:95
bool begin(DLNADevice &device, IUDPService &udp, HttpServer &server)
start the
Definition: DLNADeviceMgr.h:26
void setPostAliveRepeatMs(uint32_t ms)
Definition: DLNADeviceMgr.h:138
HttpServer * p_server
Definition: DLNADeviceMgr.h:145
void setSchedulerActive(bool flag)
We can activate/deactivate the scheduler.
Definition: DLNADeviceMgr.h:131
DLNADeviceRequestParser parser
Definition: DLNADeviceMgr.h:142
void end()
Stops the processing and releases the resources.
Definition: DLNADeviceMgr.h:77
virtual void setupServices(DLNADevice &deviceInfo)
Definition: DLNADeviceMgr.h:245
Scheduler scheduler
Definition: DLNADeviceMgr.h:141
IUDPService * p_udp
Definition: DLNADeviceMgr.h:143
DLNADevice & getDevice()
Provides the device.
Definition: DLNADeviceMgr.h:128
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:123
DLNAServiceInfo & getService(const char *id)
Finds a service definition by name.
Definition: DLNADevice.h:113
virtual void setupServices(HttpServer &server, IUDPService &udp)
Definition: DLNADevice.h:164
Url & getDeviceURL()
This method returns base url/device.xml.
Definition: DLNADevice.h:67
void print(Print &out)
renderes the device xml
Definition: DLNADevice.h:36
const char * getBaseURL()
Provides the base url.
Definition: DLNADevice.h:58
const char * getDeviceType()
Definition: DLNADevice.h:46
Icon getIcon(int idx=0)
Definition: DLNADevice.h:143
const char * getUDN()
Provide the udn uuid.
Definition: DLNADevice.h:52
virtual void loop()
Definition: DLNADevice.h:160
Attributes needed for the DLNA Service Definition.
Definition: DLNAServiceInfo.h:16
HttpHeader & put(const char *key, const char *value)
Definition: HttpHeader.h:103
void write(Client &out)
Definition: HttpHeader.h:268
void setValues(int statusCode, const char *msg="", const char *protocol=nullptr)
Definition: HttpHeader.h:416
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(int port)=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:19
const char * buildPath(const char *start, const char *p1=nullptr, const char *p2=nullptr)
Definition: StrView.h:739
virtual bool contains(const char *str)
checks if the string contains a substring
Definition: StrView.h:279
URL parser which breaks a full url string up into its individual parts.
Definition: Url.h:18
const char * path()
Definition: Url.h:47
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