Add new module to handle NAT firewalls

pull/206/head
dannybackx 8 years ago
parent ac9e0d40c0
commit 955c5a9dc6
  1. 2
      cmd/cmd.c
  2. 4
      cmd/cmd.h
  3. 4
      cmd/handlers.c
  4. 124
      esp-link/upnp.c

@ -41,7 +41,7 @@ static uint16_t resp_crc;
// Start a response, returns the partial CRC
void ICACHE_FLASH_ATTR
cmdResponseStart(uint16_t cmd, uint32_t value, uint16_t argc) {
DBG("cmdResponse: cmd=%d val=%d argc=%d\n", cmd, value, argc);
// DBG("cmdResponse: cmd=%d val=%d argc=%d\n", cmd, value, argc);
uart0_write_char(SLIP_END);
cmdProtoWriteBuf((uint8_t*)&cmd, 2);

@ -68,6 +68,10 @@ typedef enum {
CMD_WIFI_GET_SSID, // Query SSID currently connected to
CMD_WIFI_START_SCAN, // Trigger a scan (takes a long time)
CMD_UPNP_SCAN = 60,
CMD_UPNP_ADD_PORT,
CMD_UPNP_REMOVE_PORT,
} CmdName;
typedef void (*cmdfunc_t)(CmdPacket *cmd);

@ -40,6 +40,8 @@ static void cmdWifiSignalStrength(CmdPacket *cmd);
void cmdMqttGetClientId(CmdPacket *cmd);
void cmdUPnPScan(CmdPacket *cmd);
// keep track of last status sent to uC so we can notify it when it changes
static uint8_t lastWifiStatus = wifiIsDisconnected;
// keep track of whether we have registered our cb handler with the wifi subsystem
@ -64,6 +66,8 @@ const CmdList commands[] = {
{CMD_WIFI_GET_SSID, "WIFI_GET_SSID", cmdWifiQuerySSID},
{CMD_WIFI_START_SCAN, "WIFI_START_SCAN", cmdWifiStartScan},
{CMD_UPNP_SCAN, "UPNP_SCAN", cmdUPnPScan},
#ifdef MQTT
{CMD_MQTT_SETUP, "MQTT_SETUP", MQTTCMD_Setup},
{CMD_MQTT_PUBLISH, "MQTT_PUB", MQTTCMD_Publish},

@ -0,0 +1,124 @@
#include "esp8266.h"
#include "sntp.h"
#include "cmd.h"
#include <socket.h>
#include <ip_addr.h>
#if 1
#define DBG_SOCK(format, ...) os_printf(format, ## __VA_ARGS__)
#else
#define DBG_SOCK(format, ...) do { } while(0)
#endif
#define location_size 80
static const int counter_max = 4;
enum upnp_state_t {
upnp_none,
upnp_multicasted,
upnp_found_igd
};
static enum upnp_state_t upnp_state;
static const char *upnp_ssdp_multicast = "239.255.255.250";
static short upnp_server_port = 1900;
static short upnp_local_port = -1;
static const char *ssdp_message = "M-SEARCH * HTTP/1.1\r\n"
"HOST: 239.255.255.250:1900\r\n"
"ST: urn:schemas-upnp-org:device:InternetGatewayDevice:1\r\n"
"MAN: \"ssdp:discover\"\r\n"
"MX: 2\r\n";
static int ssdp_len;
static char location[location_size];
static int counter;
static void ICACHE_FLASH_ATTR
upnp_recv_cb(void *arg, char *pusrdata, unsigned short length) {
// struct espconn *pCon = (struct espconn *)arg;
os_printf("upnp_recv_cb : %d bytes\n", length);
switch (upnp_state) {
case upnp_multicasted:
// Find the LOCATION: field
for (int i=0; i<length-20; i++)
if (pusrdata[i] == 0x0D && pusrdata[i+1] == 0x0A
&& os_strncmp(pusrdata+i+2, "LOCATION:", 9) == 0) {
// find end of LOCATION field
int j, k;
for (k=j=i+11; pusrdata[k] && pusrdata[k] != 0x0D; k++) ;
int len = k-j+1;
pusrdata[k] = 0; // NULL terminate
// FIXME this should be dynamically allocated
os_strncpy(location, pusrdata+j, len);
DBG_SOCK("len %d message %s\n", len, pusrdata+j);
// Trigger next query
break;
}
break;
default:
os_printf("UPnP FSM issue\n");
}
}
// Our packets are small, so this is not useful
static void ICACHE_FLASH_ATTR
upnp_sent_cb(void *arg) {
struct espconn *con = (struct espconn *)arg;
os_printf("upnp_sent_cb\n");
if (counter < counter_max) {
counter++;
espconn_sent(con, (uint8_t*)ssdp_message, ssdp_len);
}
}
void ICACHE_FLASH_ATTR
cmdUPnPScan(CmdPacket *cmd) {
upnp_state = upnp_none;
os_printf("cmdUPnPScan()\n");
// cmdResponseStart(CMD_RESP_V, wifiState, 0);
// cmdResponseEnd();
struct espconn *con = (struct espconn *)os_zalloc(sizeof(struct espconn));
if (con == NULL) {
DBG_SOCK("SOCKET : Setup failed to alloc memory for client_pCon\n");
return;
}
counter = 0;
con->type = ESPCONN_UDP;
con->proto.udp = (esp_udp *)os_zalloc(sizeof(esp_udp));
if (con->proto.udp == NULL) {
DBG_SOCK("SOCKET : Setup failed to alloc memory for client->pCon->proto.udp\n");
return;
}
con->state = ESPCONN_NONE;
con->proto.udp->remote_port = upnp_server_port;
con->proto.udp->local_port = upnp_local_port;
espconn_regist_sentcb(con, upnp_sent_cb);
espconn_regist_recvcb(con, upnp_recv_cb);
DBG_SOCK("SOCKET : Create connection to ip %s:%d\n", upnp_ssdp_multicast, upnp_server_port);
if (UTILS_StrToIP((char *)upnp_ssdp_multicast, &con->proto.udp->remote_ip)) {
espconn_create(con);
} else {
DBG_SOCK("SOCKET : failed to copy remote_ip to &con->proto.udp->remote_ip\n");
return;
}
ssdp_len = strlen(ssdp_message);
espconn_sent(con, (uint8_t*)ssdp_message, ssdp_len);
DBG_SOCK("SOCKET : sending %d bytes\n", ssdp_len);
upnp_state = upnp_multicasted;
}
Loading…
Cancel
Save