Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

device list for M-SEARCH message #53

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ I hope this helps.
Referenced from my answer here:
https://stackoverflow.com/a/46267791/4295037

Detailed Document Released by UPnP Forum
=
http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v2.0.pdf

DDNS
=
You will also need a DDNS update service
Expand Down
89 changes: 50 additions & 39 deletions src/TinyUPnP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -519,24 +519,30 @@ void TinyUPnP::broadcastMSearch() {
_udpClient.beginMulticastPacket();
#endif

strcpy_P(body_tmp, PSTR("M-SEARCH * HTTP/1.1\r\n"));
strcat_P(body_tmp, PSTR("HOST: 239.255.255.250:"));
sprintf(integer_string, "%d", UPNP_SSDP_PORT);
strcat_P(body_tmp, integer_string);
strcat_P(body_tmp, PSTR("\r\n"));
strcat_P(body_tmp, PSTR("MAN: \"ssdp:discover\"\r\n"));
strcat_P(body_tmp, PSTR("MX: 5\r\n"));
strcat_P(body_tmp, PSTR("ST: urn:schemas-upnp-org:device:InternetGatewayDevice:1\r\n\r\n"));
for (int i = 0; deviceList[i]; i++) {
strcpy_P(body_tmp, PSTR("M-SEARCH * HTTP/1.1\r\n"));
strcat_P(body_tmp, PSTR("HOST: 239.255.255.250:"));
sprintf(integer_string, "%d", UPNP_SSDP_PORT);
strcat_P(body_tmp, integer_string);
strcat_P(body_tmp, PSTR("\r\n"));
strcat_P(body_tmp, PSTR("MAN: \"ssdp:discover\"\r\n"));
strcat_P(body_tmp, PSTR("MX: 2\r\n")); // allowed number of seconds to wait before replying to this M_SEARCH
strcat_P(body_tmp, PSTR("ST: "));
strcat_P(body_tmp, deviceList[i]);
strcat_P(body_tmp, PSTR("\r\n"));
strcat_P(body_tmp, PSTR("USER-AGENT: unix/5.1 UPnP/2.0 TinyUPnP/1.0\r\n"));
strcat_P(body_tmp, PSTR("\r\n"));

debugPrintln(body_tmp);
debugPrintln(body_tmp);

#if defined(ESP8266)
_udpClient.write(body_tmp);
_udpClient.write(body_tmp);
#else
_udpClient.print(body_tmp);
_udpClient.print(body_tmp);
#endif

_udpClient.endPacket();

_udpClient.endPacket();
}

debugPrintln(F("M-SEARCH sent"));
}
Expand All @@ -546,14 +552,19 @@ void TinyUPnP::broadcastMSearch() {
// Note: only gateway defined IGD response will be considered, the rest will be ignored
boolean TinyUPnP::waitForUnicastResponseToMSearch(gatewayInfo *deviceInfo, IPAddress gatewayIP) {
int packetSize = _udpClient.parsePacket();
// only continue is a packet is available
// only continue if a packet is available
if (packetSize <= 0) {
return false;
}

IPAddress remoteIP = _udpClient.remoteIP();
// only continue if the packet was received from the gateway router
if (remoteIP != gatewayIP) {
debugPrint(F("Discarded packet - gatewayIP ["));
debugPrint(gatewayIP.toString());
debugPrint(F("] remoteIP ["));
debugPrint(ipMulti.toString());
debugPrintln(F("]"));
return false;
}

Expand Down Expand Up @@ -598,13 +609,22 @@ boolean TinyUPnP::waitForUnicastResponseToMSearch(gatewayInfo *deviceInfo, IPAdd
debugPrintln(responseBuffer);

// only continue if the packet is a response to M-SEARCH and it originated from a gateway device
if (strstr(responseBuffer, INTERNET_GATEWAY_DEVICE) == NULL) {
boolean foundIGD = false;
for (int i = 0; deviceList[i]; i++) {
if (strstr(responseBuffer, deviceList[i]) != NULL) {
foundIGD = true;
debugPrint(F("IGD of type ["));
debugPrint(deviceList[i]);
debugPrintln(F("] found"));
break;
}
}

if (!foundIGD) {
debugPrintln(F("INTERNET_GATEWAY_DEVICE was not found"));
return false;
}

debugPrintln(F("INTERNET_GATEWAY_DEVICE found"));

String location = "";
char* location_indexStart = strstr(responseBuffer, "location:");
if (location_indexStart == NULL) {
Expand Down Expand Up @@ -730,28 +750,19 @@ boolean TinyUPnP::getIGDEventURLs(gatewayInfo *deviceInfo) {
// to support multiple <serviceType> tags
int service_type_index_start = 0;

int service_type_1_index = line.indexOf(UPNP_SERVICE_TYPE_TAG_START + UPNP_SERVICE_TYPE_1);
if (service_type_1_index >= 0) {
service_type_index_start = service_type_1_index;
service_type_1_index = line.indexOf(UPNP_SERVICE_TYPE_TAG_END, service_type_index_start);
}
int service_type_2_index = line.indexOf(UPNP_SERVICE_TYPE_TAG_START + UPNP_SERVICE_TYPE_2);
if (service_type_2_index >= 0) {
service_type_index_start = service_type_2_index;
service_type_2_index = line.indexOf(UPNP_SERVICE_TYPE_TAG_END, service_type_index_start);
}
if (!upnpServiceFound && service_type_1_index >= 0) {
index_in_line += service_type_1_index;
upnpServiceFound = true;
deviceInfo->serviceTypeName = getTagContent(line.substring(service_type_index_start), UPNP_SERVICE_TYPE_TAG_NAME);
debugPrintln(deviceInfo->serviceTypeName + " service found!");
// will start looking for 'controlURL' now
} else if (!upnpServiceFound && service_type_2_index >= 0) {
index_in_line += service_type_2_index;
upnpServiceFound = true;
deviceInfo->serviceTypeName = getTagContent(line.substring(service_type_index_start), UPNP_SERVICE_TYPE_TAG_NAME);
debugPrintln(deviceInfo->serviceTypeName + " service found!");
// will start looking for 'controlURL' now
for (int i = 0; deviceList[i]; i++) {
int service_type_index = line.indexOf(UPNP_SERVICE_TYPE_TAG_START + deviceList[i]);
if (service_type_index >= 0) {
service_type_index_start = service_type_index;
service_type_index = line.indexOf(UPNP_SERVICE_TYPE_TAG_END, service_type_index_start);
}
if (!upnpServiceFound && service_type_index >= 0) {
index_in_line += service_type_index;
upnpServiceFound = true;
deviceInfo->serviceTypeName = getTagContent(line.substring(service_type_index_start), UPNP_SERVICE_TYPE_TAG_NAME);
debugPrintln(deviceInfo->serviceTypeName + " service found! deviceTyep [" + deviceList[i] + "]");
break; // will start looking for 'controlURL' now
}
}

if (upnpServiceFound && (index_in_line = line.indexOf("<controlURL>", index_in_line)) >= 0) {
Expand Down
14 changes: 11 additions & 3 deletions src/TinyUPnP.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,20 @@
#define UPNP_DEBUG
#define UPNP_SSDP_PORT 1900
#define TCP_CONNECTION_TIMEOUT_MS 6000
#define INTERNET_GATEWAY_DEVICE "urn:schemas-upnp-org:device:InternetGatewayDevice:1"
#define PORT_MAPPING_INVALID_INDEX "<errorDescription>SpecifiedArrayIndexInvalid</errorDescription>"
#define PORT_MAPPING_INVALID_ACTION "<errorDescription>Invalid Action</errorDescription>"

static const char * const deviceList[] = {
"urn:schemas-upnp-org:device:InternetGatewayDevice:2",
"urn:schemas-upnp-org:service:WANIPConnection:2",
"urn:schemas-upnp-org:device:InternetGatewayDevice:1",
"urn:schemas-upnp-org:service:WANIPConnection:1",
"urn:schemas-upnp-org:service:WANPPPConnection:1",
"upnp:rootdevice",
"ssdp:all",
0
};

#define RULE_PROTOCOL_TCP "TCP"
#define RULE_PROTOCOL_UDP "UDP"

Expand All @@ -27,8 +37,6 @@
#define UDP_TX_PACKET_MAX_SIZE 1000 // reduce max UDP packet size to conserve memory (by default UDP_TX_PACKET_MAX_SIZE=8192)
#define UDP_TX_RESPONSE_MAX_SIZE 8192

const String UPNP_SERVICE_TYPE_1 = "urn:schemas-upnp-org:service:WANPPPConnection:";
const String UPNP_SERVICE_TYPE_2 = "urn:schemas-upnp-org:service:WANIPConnection:";
const String UPNP_SERVICE_TYPE_TAG_NAME = "serviceType";
const String UPNP_SERVICE_TYPE_TAG_START = "<serviceType>";
const String UPNP_SERVICE_TYPE_TAG_END = "</serviceType>";
Expand Down