22class DLNAControlPoint;
90 void setLocalURL(IPAddress url,
int port=9001,
const char* path=
"")
override {
92 snprintf(buffer,
sizeof(buffer),
"http://%s:%d%s", url.toString().c_str(), port,
110 std::function<
void(
const char* sid,
const char* varName,
113 void* ref =
nullptr)
override {
127 void onResultNode(std::function<
void(
const char* nodeName,
const char* text,
128 const char* attributes)>
133 bool begin(
const char* searchTarget =
"ssdp:all", uint32_t minWaitMs = 3000,
134 uint32_t maxWaitMs = 60000)
override {
137 "DLNAControlPoint::begin: transports not configured");
156 const char* searchTarget =
"ssdp:all", uint32_t minWaitMs = 3000,
157 uint32_t maxWaitMs = 60000)
override {
183 if (minWaitMs > maxWaitMs) minWaitMs = maxWaitMs;
184 search->
end_time = millis() + maxWaitMs;
192 uint64_t start = millis();
193 uint64_t minEnd = start + minWaitMs;
194 uint64_t maxEnd = start + maxWaitMs;
195 while (millis() < maxEnd) {
199 if (
devices.size() > 0 && millis() >= minEnd)
break;
209 if (
devices.size() > 0 && search !=
nullptr) {
214 "Control Point started with %d devices found",
242 for (
auto& device :
devices) device.clear();
309 if (schedule !=
nullptr) {
346 if (result)
return result;
360 if (idx < 0 || idx >=
devices.size()) {
371 for (
auto& srv : dev.getServices()) {
372 if (srv == service)
return dev;
382 if (dev.getDeviceURL() == location) {
384 "DLNAControlPointMgr::getDevice: Found device %s",
402 return getUrlImpl(device, suffix, buffer, len);
408 for (
auto& existing_device :
devices) {
409 if (dev.
getUDN() == existing_device.getUDN()) {
448 device_parser.
begin();
450 int len =
p_http->
read(buffer,
sizeof(buffer));
452 device_parser.parse(buffer, len);
454 device_parser.end(new_device);
462 for (
auto& existing_device :
devices) {
463 if (existing_device.getUDN() == new_device.
getUDN()) {
465 "Device '%s' already exists (skipping add)",
468 existing_device.setActive(
true);
525 std::function<void(
const char* nodeName,
const char* text,
526 const char* attributes)>
540 if (!usn_c || *usn_c ==
'\0')
return false;
541 const char* sep = strstr(usn_c,
"::");
542 int udn_len = sep ? (int)(sep - usn_c) : (int)strlen(usn_c);
544 const char* known_udn = dev.getUDN();
545 if (known_udn && strncmp(known_udn, usn_c, udn_len) == 0 &&
546 (int)strlen(known_udn) == udn_len) {
557 select ?
"added" :
"filtered");
558 if (!select)
return false;
563 "Device '%s' already known (skip GET)",
564 existing ? existing->
getUDN() :
"<unknown>");
573 "Device '%s' filtered by netmask (LOCATION %s)",
590 const char* peerHost = url.
host();
595 bool peerOK = (peerHost && *peerHost) ? peerIP.fromString(peerHost) :
false;
597 (localHost && *localHost) ? localIP.fromString(localHost) :
false;
600 if (!peerOK || !localOK)
return true;
602 for (
int i = 0; i < 4; i++) {
603 if ((localIP[i] & netmask[i]) != (peerIP[i] & netmask[i])) {
605 "Discovery filtered: local=%d.%d.%d.%d peer=%d.%d.%d.%d "
607 localIP[0], localIP[1], localIP[2], localIP[3],
608 peerIP[0], peerIP[1], peerIP[2], peerIP[3], netmask[0],
609 netmask[1], netmask[2], netmask[3]);
615 "Discovery accepted: local=%d.%d.%d.%d peer=%d.%d.%d.%d",
616 localIP[0], localIP[1], localIP[2], localIP[3], peerIP[0],
617 peerIP[1], peerIP[2], peerIP[3]);
624 if (nts.
equals(
"ssdp:byebye")) {
627 if (nts.
equals(
"ssdp:alive")) {
636 "DLNAControlPointMgr::processMSearchReply");
640 const char* usn_c = data.
usn.
c_str();
641 if (usn_c && *usn_c) {
642 const char* sep = strstr(usn_c,
"::");
643 int udn_len = sep ? (int)(sep - usn_c) : (int)strlen(usn_c);
645 const char* known_udn = dev.getUDN();
646 if (known_udn && strncmp(known_udn, usn_c, udn_len) == 0 &&
647 (int)strlen(known_udn) == udn_len) {
649 "MSearchReply: device '%s' already known (skip GET)",
673 for (
auto& srv : dev.getServices()) {
674 srv.is_active =
false;
675 if (usn.
endsWith(srv.service_type)) {
678 srv.is_active =
false;
708 "xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
709 "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"",
714 StrView namespace_str(ns, 200);
715 namespace_str =
"xmlns:u=\"%1\"";
721 namespace_str.
c_str(),
"u");
723 const char* n = arg.name.c_str();
724 const char* v = arg.value.c_str();
760 action_str.add(
"\"");
766 "Service control_url: %s, device base: %s",
788 const char* soapAction,
791 "DLNAControlPointMgr::processActionHttpPost");
796 auto printXML = [
this, &action, &xmlLen](Print& out,
void* ref) ->
size_t {
802 int rc =
p_http->
post(post_url, xmlLen, printXML,
"text/xml");
809 StrView(soapAction).c_str(), rc);
821 if (c) xmlProcessor(*c,
reply);
848 xml_parser.
write(buffer, len);
849 while (xml_parser.
parse(outNodeName, outPath, outText, outAttributes)) {
856 outNodeName.
equals(
"Result")) {
869 StrView(outAttributes).c_str());
872 StrView(outNodeName ? outNodeName :
"").c_str(),
873 StrView(outText ? outText :
"").c_str(),
874 StrView(outAttributes ? outAttributes :
"").c_str());
890 const char* buffer,
int len) {
892 StrView url_str{(
char*)buffer, len};
895 if (base !=
nullptr && *base !=
'\0') {
906 if (suffix !=
nullptr && suffix[0] !=
'\0') {
907 int base_len = url_str.length();
908 const char* tmpc = url_str.c_str();
909 bool base_ends_slash =
910 tmpc !=
nullptr && base_len > 0 && tmpc[base_len - 1] ==
'/';
911 bool suf_starts_slash = suffix[0] ==
'/';
912 if (base_ends_slash && suf_starts_slash) {
914 url_str.add(suffix + 1);
915 }
else if (!base_ends_slash && !suf_starts_slash) {
Represents the result of invoking a DLNA service Action.
Definition: Action.h:48
int size()
Definition: Action.h:79
void clear()
Definition: Action.h:81
void setValid(bool flag)
Definition: Action.h:52
void addArgument(Argument arg)
Definition: Action.h:59
void logArguments()
Definition: Action.h:83
Represents a request to invoke a remote DLNA service action.
Definition: Action.h:104
DLNAServiceInfo * getService()
Definition: Action.h:163
const char * getAction()
Definition: Action.h:157
Vector< Argument > & getArguments()
Definition: Action.h:165
DLNA Service: Action Argument.
Definition: Action.h:17
Str value
Definition: Action.h:25
Str name
Definition: Action.h:24
Translates DLNA UDP Requests to Schedule so that we can schedule a reply.
Definition: DLNAControlPointRequestParser.h:15
Schedule * parse(RequestData &req)
Definition: DLNAControlPointRequestParser.h:17
Lightweight DLNA control point manager.
Definition: DLNAControlPoint.h:61
static bool handleNotifyByebye(Str &usn)
Definition: DLNAControlPoint.h:531
void * reference
Definition: DLNAControlPoint.h:524
void setSubscribeNotificationsActive(bool flag) override
Activate/deactivate subscription notifications.
Definition: DLNAControlPoint.h:497
void setHttpServer(IHttpServer &server) override
Set HttpServer instance and register the notify handler.
Definition: DLNAControlPoint.h:118
void end() override
Stops the processing and releases the resources.
Definition: DLNAControlPoint.h:226
DLNAControlPoint(IHttpServer &server)
Constructor supporting Notifications.
Definition: DLNAControlPoint.h:79
size_t createSoapXML(ActionRequest &action, Print &out)
Build the SOAP XML request body for the action into out
Definition: DLNAControlPoint.h:780
bool matches(const char *usn)
checks if the usn contains the search target
Definition: DLNAControlPoint.h:663
size_t createXML(ActionRequest &action)
Definition: DLNAControlPoint.h:702
static bool processMSearchReply(MSearchReplyCP &data)
Processes an M-SEARCH HTTP 200 reply and attempts to add the device.
Definition: DLNAControlPoint.h:634
int default_device_idx
Definition: DLNAControlPoint.h:516
static bool handleNotifyAlive(NotifyReplyCP &data)
Definition: DLNAControlPoint.h:554
bool addDevice(Url url) override
Adds the device from the device xml url if it does not already exist.
Definition: DLNAControlPoint.h:422
bool is_parse_device
Definition: DLNAControlPoint.h:519
Vector< DLNADeviceInfo > devices
Definition: DLNAControlPoint.h:512
const char * getUrlImpl(DLNADeviceInfo &device, const char *suffix, const char *buffer, int len)
Definition: DLNAControlPoint.h:889
Url local_url
Definition: DLNAControlPoint.h:521
bool addDevice(DLNADeviceInfo dev) override
Adds a new device.
Definition: DLNAControlPoint.h:406
bool allow_localhost
Definition: DLNAControlPoint.h:522
IHttpServer * p_http_server
Definition: DLNAControlPoint.h:523
Scheduler scheduler
Definition: DLNAControlPoint.h:508
~DLNAControlPoint() override=default
bool is_active
Definition: DLNAControlPoint.h:518
void setLocalURL(Url url) override
Defines the local url (needed for subscriptions)
Definition: DLNAControlPoint.h:89
void setTransports(IHttpRequest &http, IUDPService &udp)
Definition: DLNAControlPoint.h:220
const char * registerString(const char *s) override
Register a string in the shared registry and return the stored pointer.
Definition: DLNAControlPoint.h:502
SubscriptionMgrControlPoint * getSubscriptionMgr() override
Provides the subscription manager.
Definition: DLNAControlPoint.h:492
DLNADeviceInfo NO_DEVICE
Definition: DLNAControlPoint.h:507
void parseResult()
Parses the XML response from the HTTP client and populates reply arguments.
Definition: DLNAControlPoint.h:837
const char * getUrl(DLNADeviceInfo &device, const char *suffix, char *buffer, int len) override
Definition: DLNAControlPoint.h:400
DLNAServiceInfo & getService(const char *id) override
Provide addess to the service information.
Definition: DLNAControlPoint.h:341
void setDeviceIndex(int idx) override
Selects the default device by index.
Definition: DLNAControlPoint.h:106
void setSearchRepeatMs(int repeatMs) override
Sets the repeat interval for M-SEARCH requests (define before begin)
Definition: DLNAControlPoint.h:98
int msearch_repeat_ms
Definition: DLNAControlPoint.h:517
void setActive(bool flag) override
We can activate/deactivate the scheduler.
Definition: DLNAControlPoint.h:480
void setEventSubscriptionCallback(std::function< void(const char *sid, const char *varName, const char *newValue, void *reference)> cb, void *ref=nullptr) override
Register a callback that will be invoked for incoming event notification.
Definition: DLNAControlPoint.h:109
ActionReply & processActionHttpPost(ActionRequest &action, Url &post_url, const char *soapAction, XMLCallback xmlProcessor=nullptr)
Processes an HTTP POST request for the given action and URL.
Definition: DLNAControlPoint.h:787
void setLocalURL(IPAddress url, int port=9001, const char *path="") override
Set the local callback URL for event subscriptions.
Definition: DLNAControlPoint.h:90
Vector< ActionRequest > actions
Definition: DLNAControlPoint.h:513
bool isActive() override
Checks if the scheduler is active.
Definition: DLNAControlPoint.h:483
bool loop() override
Definition: DLNAControlPoint.h:298
static bool isUdnKnown(const char *usn_c, DLNADeviceInfo *&outDev)
Definition: DLNAControlPoint.h:538
ActionReply & getLastReply() override
Provides the last reply.
Definition: DLNAControlPoint.h:489
const char * search_target
Definition: DLNAControlPoint.h:520
void onResultNode(std::function< void(const char *nodeName, const char *text, const char *attributes)> cb) override
Definition: DLNAControlPoint.h:127
DLNADeviceInfo & getDevice() override
Provides the device information of the actually selected device.
Definition: DLNAControlPoint.h:352
static bool processDevice(NotifyReplyCP &data)
Definition: DLNAControlPoint.h:621
std::function< void(const char *nodeName, const char *text, const char *attributes)> result_callback
Definition: DLNAControlPoint.h:527
DLNADeviceInfo & getDevice(int idx) override
Provides the device information by index.
Definition: DLNAControlPoint.h:358
bool processBye(Str &usn)
processes a bye-bye message
Definition: DLNAControlPoint.h:669
DLNADeviceInfo & getDevice(Url location) override
Get a device for a Url.
Definition: DLNAControlPoint.h:379
ActionReply & postAction(ActionRequest &action, XMLCallback xmlProcessor=nullptr)
Definition: DLNAControlPoint.h:745
ActionReply reply
Definition: DLNAControlPoint.h:514
void setParseDevice(bool flag) override
Requests the parsing of the device information.
Definition: DLNAControlPoint.h:86
Vector< DLNADeviceInfo > & getDevices() override
Get list of all discovered devices.
Definition: DLNAControlPoint.h:392
bool begin(IHttpRequest &http, IUDPService &udp, const char *searchTarget="ssdp:all", uint32_t minWaitMs=3000, uint32_t maxWaitMs=60000) override
Start discovery by sending M-SEARCH requests and process replies.
Definition: DLNAControlPoint.h:155
IHttpRequest * p_http
Definition: DLNAControlPoint.h:509
bool begin(const char *searchTarget="ssdp:all", uint32_t minWaitMs=3000, uint32_t maxWaitMs=60000) override
Start discovery with default HTTP/UDP services.
Definition: DLNAControlPoint.h:133
DLNADeviceInfo & getDevice(DLNAServiceInfo &service) override
Provides the device for a service.
Definition: DLNAControlPoint.h:368
ActionReply & postAllActions(XMLCallback xmlProcessor=nullptr)
Definition: DLNAControlPoint.h:736
ActionReply & executeActions(XMLCallback xmlProcessor=nullptr) override
Executes action and parses the reply xml to collect the reply entries. If an XML processor is provide...
Definition: DLNAControlPoint.h:284
DLNAControlPoint(IHttpRequest &http, IUDPService &udp, IHttpServer &server)
Constructor wiring HTTP and UDP dependencies; notifications disabled.
Definition: DLNAControlPoint.h:72
ActionRequest & addAction(ActionRequest act) override
Registers a method that will be called.
Definition: DLNAControlPoint.h:270
XMLPrinter xml_printer
Definition: DLNAControlPoint.h:515
bool isDiscoveryAllowed(Url &url)
Definition: DLNAControlPoint.h:587
DLNAControlPoint(IHttpRequest &http, IUDPService &udp)
Constructor wiring HTTP and UDP dependencies; notifications disabled.
Definition: DLNAControlPoint.h:67
DLNAControlPoint()
Default constructor w/o Notifications.
Definition: DLNAControlPoint.h:64
void setReference(void *ref) override
Attach an opaque reference pointer (optional, for caller context)
Definition: DLNAControlPoint.h:103
SubscriptionMgrControlPoint subscription_mgr
Definition: DLNAControlPoint.h:511
void unEscapeStr(Str &str)
Definition: DLNAControlPoint.h:883
void setAllowLocalhost(bool flag) override
Defines if localhost devices should be allowed.
Definition: DLNAControlPoint.h:486
IUDPService * p_udp
Definition: DLNAControlPoint.h:510
Device Attributes and generation of XML using urn:schemas-upnp-org:device-1-0. We could just return a...
Definition: DLNADeviceInfo.h:25
Url device_url
Definition: DLNADeviceInfo.h:254
Str base_url
Definition: DLNADeviceInfo.h:258
const char * getUDN()
Provide the udn uuid.
Definition: DLNADeviceInfo.h:88
const char * getBaseURL()
Provides the base url.
Definition: DLNADeviceInfo.h:118
virtual bool begin()
Override to initialize the device.
Definition: DLNADeviceInfo.h:59
Url & getDeviceURL()
This method returns base url/device.xml.
Definition: DLNADeviceInfo.h:129
void setActive(bool flag)
Sets the server to inactive.
Definition: DLNADeviceInfo.h:237
Attributes needed for the DLNA Service Definition.
Definition: DLNAServiceInfo.h:18
Str service_type
Definition: DLNAServiceInfo.h:37
Str control_url
Definition: DLNAServiceInfo.h:40
Abstract interface for DLNA Control Point functionality.
Definition: IControlPoint.h:43
Abstract interface for HTTP client request functionality.
Definition: IHttpRequest.h:21
virtual void setTimeout(int ms)=0
Set request timeout in milliseconds.
virtual Client * client()=0
Get pointer to client.
virtual int read(uint8_t *str, int len)=0
Read data from response.
virtual HttpRequestHeader & request()=0
Get reference to request header.
virtual int post(Url &url, const char *mime, const char *data, int len=-1)=0
Send POST request with string data.
virtual void stop()=0
Stop the connection.
virtual int get(Url &url, const char *acceptMime=nullptr, const char *data=nullptr, int len=-1)=0
Send GET request.
Abstract interface for HTTP server functionality.
Definition: IHttpServer.h:30
virtual bool begin()=0
Start the HTTP server.
virtual bool doLoop()=0
Process server loop.
virtual void end()=0
Stop the HTTP server.
virtual bool isActive()=0
Check if server is active.
Abstract Interface for UDP API.
Definition: IUDPService.h:33
virtual RequestData receive()=0
Receive incoming UDP data and peer information.
virtual bool begin(int port)=0
Initialize UDP service on specified port.
Processing at control point to handle a MSearchReply from the device.
Definition: Schedule.h:148
Str usn
Definition: Schedule.h:152
Str location
Definition: Schedule.h:151
Send MSearch request.
Definition: Schedule.h:46
Represents a notification/notify reply scheduled for control-point processing.
Definition: Schedule.h:189
Str nts
Definition: Schedule.h:192
Class with does not do any output: it can be used to determine the length of the output.
Definition: NullPrint.h:12
Scheduler which processes all due Schedules (to send out UDP replies)
Definition: Scheduler.h:15
int execute(IUDPService &udp)
Execute all due schedules.
Definition: Scheduler.h:30
void setActive(bool flag)
Definition: Scheduler.h:81
int size()
Number of queued schedules.
Definition: Scheduler.h:79
bool isMSearchActive()
Returns true if there is any active schedule with name "MSearch".
Definition: Scheduler.h:69
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:18
virtual void add(int value)
adds a int value
Definition: StrView.h:128
virtual const char * c_str()
provides the string value as const char*
Definition: StrView.h:376
virtual bool replace(const char *toReplace, const int replaced)
Replaces the first instance of toReplace with replaced.
Definition: StrView.h:395
virtual bool equals(const char *str)
checks if the string equals indicated parameter string
Definition: StrView.h:177
virtual bool contains(const char *str)
checks if the string contains a substring
Definition: StrView.h:284
Heap-backed string utility used throughout tiny_dlna.
Definition: Str.h:27
bool equals(const char *other) const
Exact string equality with C-string.
Definition: Str.h:167
bool isEmpty() const
True if empty.
Definition: Str.h:54
bool endsWith(const char *suffix) const
True if ends with suffix (case-sensitive)
Definition: Str.h:175
bool startsWith(const char *prefix) const
True if starts with prefix (case-sensitive)
Definition: Str.h:206
int replaceAll(const char *toReplace, const char *replaced)
Replace all occurrences of toReplace with replaced; returns count.
Definition: Str.h:279
void clear()
Clear contents (size -> 0)
Definition: Str.h:93
const char * c_str() const
C-string pointer to internal buffer.
Definition: Str.h:88
Standalone manager for UPnP/DLNA event subscriptions used by control points and devices.
Definition: SubscriptionMgrControlPoint.h:44
void setEventSubscriptionCallback(std::function< void(const char *sid, const char *varName, const char *newValue, void *reference)> callback, void *ref=nullptr)
Register a callback invoked when event properties change.
Definition: SubscriptionMgrControlPoint.h:108
bool loop()
Periodic work to manage subscription renewals and retries.
Definition: SubscriptionMgrControlPoint.h:198
void setHttpServer(IHttpServer &server)
Attach an HttpServer instance and register the internal NOTIFY handler.
Definition: SubscriptionMgrControlPoint.h:84
void setup(IHttpRequest &http, IUDPService &udp, Url &localCallbackUrl, DLNADeviceInfo &device)
Inject required dependencies and initialize the manager.
Definition: SubscriptionMgrControlPoint.h:62
void setEventSubscriptionActive(bool active)
Turn automatic event subscription on or off.
Definition: SubscriptionMgrControlPoint.h:172
URL parser which breaks a full url string up into its individual parts.
Definition: Url.h:18
int port()
Definition: Url.h:46
const char * host()
Definition: Url.h:41
const char * urlRoot()
Definition: Url.h:43
const char * protocol()
Definition: Url.h:42
void setUrl(const char *url)
Definition: Url.h:48
const char * url()
Definition: Url.h:39
void clear()
Definition: Url.h:63
Lightweight wrapper around std::vector with Arduino-friendly helpers and a pluggable allocator.
Definition: Vector.h:39
Incremental XML device parser using XMLParserPrint.
Definition: XMLDeviceParser.h:20
Helper class that implements a Print interface to accumulate XML data and then parse it using XMLPars...
Definition: XMLParserPrint.h:16
size_t write(uint8_t ch) override
Writes a single byte to the buffer (Print interface)
Definition: XMLParserPrint.h:32
void setExpandEncoded(bool flag)
Forwards expand-entities setting to the underlying XMLParser.
Definition: XMLParserPrint.h:48
void end()
Resets the internal buffer.
Definition: XMLParserPrint.h:87
bool parse(Str &outNodeName, Vector< Str > &outPath, Str &outText, Str &outAttributes)
Parses the accumulated XML data and returns results via output parameters.
Definition: XMLParserPrint.h:59
#define DLNA_MAX_URL_LEN
app-wide max URL length
Definition: dlna_config.h:45
#define XML_PARSER_BUFFER_SIZE
Define XML parse buffer size.
Definition: dlna_config.h:25
#define DLNA_HTTP_REQUEST_TIMEOUT_MS
Define the default http request timeout.
Definition: dlna_config.h:20
#define DLNA_DISCOVERY_NETMASK
Define the netmask for discovery filtering.
Definition: dlna_config.h:187
Definition: Allocator.h:13
DLNAControlPoint * selfDLNAControlPoint
Definition: DLNAControlPoint.h:23
std::function< void(Client &client, ActionReply &reply)> XMLCallback
Definition: IControlPoint.h:25
Provides information of the received UDP which consists of the (xml) data and the peer address and po...
Definition: IUDPService.h:22
An individual Schedule (to send out UDP messages)
Definition: Schedule.h:18
uint64_t end_time
Definition: Schedule.h:25
bool active
Definition: Schedule.h:27
virtual const char * name()
Definition: Schedule.h:35
uint32_t repeat_ms
Definition: Schedule.h:23
Functions to efficiently output XML. XML data contains a lot of redundancy so it is more memory effic...
Definition: XMLPrinter.h:56
size_t printNodeBegin(const char *node, const char *attributes=nullptr, const char *ns=nullptr)
Prints the beginning of an XML node.
Definition: XMLPrinter.h:314
size_t printNode(XMLNode node)
Prints an XML node from XMLNode struct.
Definition: XMLPrinter.h:89
size_t printNodeEnd(const char *node, const char *ns=nullptr)
Prints the end of an XML node.
Definition: XMLPrinter.h:352
void setOutput(Print &output)
Defines the output Print object.
Definition: XMLPrinter.h:73
size_t printXMLHeader()
Prints the XML header.
Definition: XMLPrinter.h:79
void clear()
Definition: XMLPrinter.h:363