Add documentation for the calls used, and yet another API.

pull/206/head
dannybackx 8 years ago
parent 606454128b
commit fab6d5bb10
  1. 1
      cmd/cmd.h
  2. 2
      cmd/handlers.c
  3. 184
      esp-link/upnp.c

@ -72,6 +72,7 @@ typedef enum {
CMD_UPNP_ADD_PORT,
CMD_UPNP_REMOVE_PORT,
CMD_UPNP_BEGIN,
CMD_UPNP_QUERY_EXTERNAL_ADDRESS
} CmdName;

@ -44,6 +44,7 @@ void cmdUPnPScan(CmdPacket *cmd);
void cmdUPnPAddPort(CmdPacket *cmd);
void cmdUPnPRemovePort(CmdPacket *cmd);
void cmdUPnPBegin(CmdPacket *cmd);
void cmdUPnPQueryExternalAddress(CmdPacket *cmd);
// keep track of last status sent to uC so we can notify it when it changes
static uint8_t lastWifiStatus = wifiIsDisconnected;
@ -73,6 +74,7 @@ const CmdList commands[] = {
{CMD_UPNP_ADD_PORT, "UPNP_ADD_PORT", cmdUPnPAddPort},
{CMD_UPNP_REMOVE_PORT, "UPNP_REMOVE_PORT", cmdUPnPRemovePort},
{CMD_UPNP_BEGIN, "UPNP_BEGIN", cmdUPnPBegin},
{CMD_UPNP_QUERY_EXTERNAL_ADDRESS, "UPNP_EXT_ADDR", cmdUPnPQueryExternalAddress},
#ifdef MQTT
{CMD_MQTT_SETUP, "MQTT_SETUP", MQTTCMD_Setup},

@ -18,7 +18,10 @@ enum upnp_state_t {
};
static enum upnp_state_t upnp_state;
/*
* Query #1 : SSDP protocol, this is a UDP multicast to discover a IGD device.
* (internet gateway device)
*/
static const char *upnp_ssdp_multicast = "239.255.255.250";
static short upnp_server_port = 1900;
static const char *ssdp_message = "M-SEARCH * HTTP/1.1\r\n"
@ -31,6 +34,167 @@ static int ssdp_len;
static char *control_url = 0;
static int counter;
/*
* Query #2 : query the IGD for its device & service list.
* We search this list for the control URL of the router.
* The protocol is now UPnP (universal plug and play), HTTP over TCP, usually with SOAP XML
* encoding. In this particular query, the query itself is a HTTP GET, no XML.
* But its reply is SOAP XML formatted.
*/
// BTW, use http/1.0 to avoid responses with transfer-encoding: chunked
static const char *general_upnp_query = "GET %s HTTP/1.0\r\n"
"Host: %s\r\n"
"Connection: close\r\n"
"User-Agent: esp-link\r\n\r\n";
/*
* Subsequent queries aren't necessarily in order
*
* This one queries the IGD for its external IP address.
*/
static const char *upnp_query_external_address = "POST %s HTTP/1.0\r\n" // control-url
"Host: %s\r\n" // host ip+port
"User-Agent: esp-link\r\n"
"Content-Length : %d\r\n" // XML length
"Content-Type: text/xml\r\n"
"SOAPAction: \"urn:schemas-upnp-org:service:WANPPPConnection:1#GetExternalIPAddress\"\r\n"
"Connection: Close\r\n"
"Cache-Control: no-cache\r\n"
"Pragma: no-cache\r\n"
"\r\n";
static const char *upnp_query_external_address_xml =
"<?xml version=\"1.0\"?>\r\n"
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n"
"<s:Body>\r\n"
"<u:GetExternalIPAddress xmlns:u=\"urn:schemas-upnp-org:service:WANPPPConnection:1\">\r\n"
"</u:GetExternalIPAddress>\r\n"
"</s:Body>\r\n"
"</s:Envelope>\r\n";
/*
Sample query
POST /o8ee3npj36j/IGD/upnp/control/igd/wanpppc_1_1_1 HTTP/1.1
Host: 192.168.1.1:8000
User-Agent: Ubuntu/16.04, UPnP/1.1, MiniUPnPc/2.0
Content-Length: 286
Content-Type: text/xml
SOAPAction: "urn:schemas-upnp-org:service:WANPPPConnection:1#GetExternalIPAddress"
Connection: Close
Cache-Control: no-cache
Pragma: no-cache
<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<u:GetExternalIPAddress xmlns:u="urn:schemas-upnp-org:service:WANPPPConnection:1">
</u:GetExternalIPAddress>
</s:Body>
</s:Envelope>
and its reply
<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<m:GetExternalIPAddressResponse
xmlns:m="urn:schemas-upnp-org:service:WANPPPConnection:1">
<NewExternalIPAddress>213.49.166.224</NewExternalIPAddress>
</m:GetExternalIPAddressResponse>
</s:Body>
</s:Envelope>
*/
/*
* This query adds a port mapping
POST /o8ee3npj36j/IGD/upnp/control/igd/wanpppc_1_1_1 HTTP/1.1
Host: 192.168.1.1:8000
User-Agent: Ubuntu/16.04, UPnP/1.1, MiniUPnPc/2.0
Content-Length: 594
Content-Type: text/xml
SOAPAction: "urn:schemas-upnp-org:service:WANPPPConnection:1#AddPortMapping"
Connection: Close
Cache-Control: no-cache
Pragma: no-cache
<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<u:AddPortMapping xmlns:u="urn:schemas-upnp-org:service:WANPPPConnection:1">
<NewRemoteHost></NewRemoteHost>
<NewExternalPort>9876</NewExternalPort>
<NewProtocol>TCP</NewProtocol>
<NewInternalPort>80</NewInternalPort>
<NewInternalClient>192.168.1.176</NewInternalClient>
<NewEnabled>1</NewEnabled>
<NewPortMappingDescription>libminiupnpc</NewPortMappingDescription>
<NewLeaseDuration>0</NewLeaseDuration>
</u:AddPortMapping>
</s:Body>
</s:Envelope>
and the reply
HTTP/1.0 200 OK
Connection: close
Date: Sat, 25 Mar 2017 16:54:41 GMT
Server: MediaAccess TG 789Ovn Xtream 10.A.0.I UPnP/1.0 (9C-97-26-26-44-DE)
Content-Length: 300
Content-Type: text/xml; charset="utf-8"
EXT:
<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<m:AddPortMappingResponse xmlns:m="urn:schemas-upnp-org:service:WANPPPConnection:1">
</m:AddPortMappingResponse>
</s:Body>
</s:Envelope>
*/
/*
* Query to delete a port mapping
POST /o8ee3npj36j/IGD/upnp/control/igd/wanpppc_1_1_1 HTTP/1.1
Host: 192.168.1.1:8000
User-Agent: Ubuntu/16.04, UPnP/1.1, MiniUPnPc/2.0
Content-Length: 380
Content-Type: text/xml
SOAPAction: "urn:schemas-upnp-org:service:WANPPPConnection:1#DeletePortMapping"
Connection: Close
Cache-Control: no-cache
Pragma: no-cache
<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<u:DeletePortMapping xmlns:u="urn:schemas-upnp-org:service:WANPPPConnection:1">
<NewRemoteHost>
</NewRemoteHost>
<NewExternalPort>9876</NewExternalPort>
<NewProtocol>TCP</NewProtocol>
</u:DeletePortMapping>
</s:Body>
</s:Envelope>
and its reply :
<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<m:DeletePortMappingResponse xmlns:m="urn:schemas-upnp-org:service:WANPPPConnection:1">
</m:DeletePortMappingResponse>
</s:Body>
</s:Envelope>
*/
typedef struct {
char *host, *path, *location;
uint32_t port, remote_port;
@ -105,12 +269,6 @@ ssdp_sent_cb(void *arg) {
#endif
}
// BTW, use http/1.0 to avoid responses with transfer-encoding: chunked
const char *http_tmpl1 = "GET %s HTTP/1.0\r\n"
"Host: %s\r\n"
"Connection: close\r\n"
"User-Agent: esp-link\r\n\r\n";
/*
* This should be a generic function that performs a query via TCP.
*/
@ -137,8 +295,8 @@ static void ICACHE_FLASH_ATTR upnp_query_igd(UPnPClient *client) {
* os_sprintf(query, tmpl, "/o8ee3npj36j/IGD/upnp/IGD.xml", "http://192.168.1.1:8000");
* upnp_query_igd(query);
*/
query = (char *)os_malloc(strlen(http_tmpl1) + strlen(client->path) + strlen(client->location));
os_sprintf(query, http_tmpl1, client->path, client->location);
query = (char *)os_malloc(strlen(general_upnp_query) + strlen(client->path) + strlen(client->location));
os_sprintf(query, general_upnp_query, client->path, client->location);
break;
default:
os_printf("upnp_query_igd: untreated state %d\n", (int)upnp_state);
@ -474,8 +632,8 @@ cmdUPnPAddPort(CmdPacket *cmd) {
client->con->type = ESPCONN_TCP;
client->con->state = ESPCONN_NONE;
char *query = (char *)os_malloc(strlen(http_tmpl1) + strlen(client->path) + strlen(client->location));
os_sprintf(query, http_tmpl1, client->path, client->location);
char *query = (char *)os_malloc(strlen(general_upnp_query) + strlen(client->path) + strlen(client->location));
os_sprintf(query, general_upnp_query, client->path, client->location);
client->data = query;
client->data_len = strlen(query);
@ -581,3 +739,7 @@ upnp_analyze_location(UPnPClient *client, char *orig_loc, int len) {
client->host = os_malloc(strlen(client->location + 7) + 1);
strcpy(client->host, client->location+7);
}
void ICACHE_FLASH_ATTR
cmdUPnPQueryExternalAddress(CmdPacket *cmd) {
}

Loading…
Cancel
Save