static void socket_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) { NODE_DBG("socket_dns_found is called.\n"); struct espconn *pesp_conn = arg; if(pesp_conn == NULL){ NODE_DBG("pesp_conn null.\n"); return; } lnet_userdata *nud = (lnet_userdata *)pesp_conn->reverse; if(nud == NULL) return; if(gL == NULL) return; if(ipaddr == NULL) { dns_reconn_count++; if( dns_reconn_count >= 5 ){ NODE_ERR( "DNS Fail!\n" ); lua_gc(gL, LUA_GCSTOP, 0); if(nud->self_ref != LUA_NOREF){ luaL_unref(gL, LUA_REGISTRYINDEX, nud->self_ref); nud->self_ref = LUA_NOREF; // unref this, and the net.socket userdata will delete it self } lua_gc(gL, LUA_GCRESTART, 0); return; } NODE_ERR( "DNS retry %d!\n", dns_reconn_count ); host_ip.addr = 0; espconn_gethostbyname(pesp_conn, name, &host_ip, socket_dns_found); return; } // ipaddr->addr is a uint32_t ip if(ipaddr->addr != 0) { dns_reconn_count = 0; if( pesp_conn->type == ESPCONN_TCP ) { c_memcpy(pesp_conn->proto.tcp->remote_ip, &(ipaddr->addr), 4); NODE_DBG("TCP ip is set: "); NODE_DBG(IPSTR, IP2STR(&(ipaddr->addr))); NODE_DBG("\n"); } else if (pesp_conn->type == ESPCONN_UDP) { c_memcpy(pesp_conn->proto.udp->remote_ip, &(ipaddr->addr), 4); NODE_DBG("UDP ip is set: "); NODE_DBG(IPSTR, IP2STR(&(ipaddr->addr))); NODE_DBG("\n"); } socket_connect(pesp_conn); } }
// Lua: format() static int file_format( lua_State* L ) { size_t len; file_close(L); if( !fs_format() ) { NODE_ERR( "\ni*** ERROR ***: unable to format. FS might be compromised.\n" ); NODE_ERR( "It is advised to re-flash the NodeMCU image.\n" ); } else{ NODE_ERR( "format done.\n" ); } return 0; }
int strbuf_init(strbuf_t *s, int len) { int size; if (len <= 0) size = STRBUF_DEFAULT_SIZE; else size = len + 1; /* \0 terminator */ s->buf = NULL; s->size = size; s->length = 0; s->increment = STRBUF_DEFAULT_INCREMENT; s->dynamic = 0; s->reallocs = 0; s->debug = 0; s->buf = (char *)cjson_mem_malloc(size); if (!s->buf){ NODE_ERR("not enough memory\n"); return -1; } strbuf_ensure_null(s); return 0; }
static int calculate_new_size(strbuf_t *s, int len) { int reqsize, newsize; if (len <= 0){ NODE_ERR("BUG: Invalid strbuf length requested"); return 0; } /* Ensure there is room for optional NULL termination */ reqsize = len + 1; /* If the user has requested to shrink the buffer, do it exactly */ if (s->size > reqsize) return reqsize; newsize = s->size; if (s->increment < 0) { /* Exponential sizing */ while (newsize < reqsize) newsize *= -s->increment; } else { /* Linear sizing */ newsize = (((reqsize -1) / s->increment) + 1) * s->increment; } return newsize; }
static inline void debug_stats(strbuf_t *s) { if (s->debug) { NODE_ERR("strbuf(%lx) reallocs: %d, length: %d, size: %d\n", (long)s, s->reallocs, s->length, s->size); } }
void nodemcu_init(void) { NODE_ERR("\n"); // Initialize platform first for lua modules. if( platform_init() != PLATFORM_OK ) { // This should never happen NODE_DBG("Can not init platform for modules.\n"); return; } #if defined(FLASH_SAFE_API) if( flash_safe_get_size_byte() != flash_rom_get_size_byte()) { NODE_ERR("Self adjust flash size.\n"); // Fit hardware real flash size. flash_rom_set_size_byte(flash_safe_get_size_byte()); if( !fs_format() ) { NODE_ERR( "\ni*** ERROR ***: unable to format. FS might be compromised.\n" ); NODE_ERR( "It is advised to re-flash the NodeMCU image.\n" ); } else { NODE_ERR( "format done.\n" ); } fs_unmount(); // mounted by format. // Reboot to get SDK to use (or write) init data at new location system_restart (); // Don't post the start_lua task, we're about to reboot... return; } #endif // defined(FLASH_SAFE_API) #if defined ( BUILD_SPIFFS ) fs_mount(); // test_spiffs(); #endif // endpoint_setup(); task_post_low(task_get_id(start_lua),'s'); }
static void socket_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) { NODE_DBG("socket_dns_found is called.\n"); struct espconn *pesp_conn = arg; if(pesp_conn == NULL){ NODE_DBG("pesp_conn null.\n"); return; } if(ipaddr == NULL) { dns_reconn_count++; if( dns_reconn_count >= 5 ){ NODE_ERR( "DNS Fail!\n" ); return; } NODE_ERR( "DNS retry %d!\n", dns_reconn_count ); host_ip.addr = 0; espconn_gethostbyname(pesp_conn, name, &host_ip, socket_dns_found); return; } // ipaddr->addr is a uint32_t ip if(ipaddr->addr != 0) { dns_reconn_count = 0; if( pesp_conn->type == ESPCONN_TCP ) { c_memcpy(pesp_conn->proto.tcp->remote_ip, &(ipaddr->addr), 4); NODE_DBG("TCP ip is set: "); NODE_DBG(IPSTR, IP2STR(&(ipaddr->addr))); NODE_DBG("\n"); } else if (pesp_conn->type == ESPCONN_UDP) { c_memcpy(pesp_conn->proto.udp->remote_ip, &(ipaddr->addr), 4); NODE_DBG("UDP ip is set: "); NODE_DBG(IPSTR, IP2STR(&(ipaddr->addr))); NODE_DBG("\n"); } socket_connect(pesp_conn); } }
void nodemcu_init(void) { NODE_DBG("Hello World!.\n"); NODE_ERR("\n"); // Initialize platform first for lua modules. if( platform_init() != PLATFORM_OK ) { // This should never happen NODE_DBG("Can not init platform for modules.\n"); return; } #if defined(FLASH_SAFE_API) if( flash_safe_get_size_byte() != flash_rom_get_size_byte()) { NODE_ERR("Self adjust flash size.\n"); // Fit hardware real flash size. flash_rom_set_size_byte(flash_safe_get_size_byte()); // Write out init data at real location. no_init_data = true; } #endif // defined(FLASH_SAFE_API) NODE_DBG("Yoink 1.\n"); if (no_init_data) { NODE_ERR("Restore init data.\n"); // Flash init data at FLASHSIZE - 0x04000 Byte. flash_init_data_default(); // Flash blank data at FLASHSIZE - 0x02000 Byte. flash_init_data_blank(); // Reboot to make the new data come into effect system_restart (); } NODE_DBG("Yoink 2.\n"); tcp_random_port_init (); NODE_DBG("Yoink 3.\n"); system_os_post(LUA_TASK_PRIO, 0, 0); }
static inline esp_image_header_t flash_load_rom_header (void) { esp_image_header_t hdr; if (ESP_OK != spi_flash_read (FLASH_HDR_ADDR, (uint32_t *)&hdr, sizeof (hdr))) { NODE_ERR("Failed to load flash header block!\n"); abort(); } return hdr; }
/* Ensure strbuf can handle a string length bytes long (ignoring NULL * optional termination). */ int strbuf_resize(strbuf_t *s, int len) { int newsize; newsize = calculate_new_size(s, len); if (s->debug > 1) { NODE_ERR("strbuf(%lx) resize: %d => %d\n", (long)s, s->size, newsize); } s->buf = (char *)cjson_mem_realloc(s->buf, newsize); if (!s->buf){ NODE_ERR("not enough memory"); return -1; } s->size = newsize; s->reallocs++; return 0; }
int strbuf_set_increment(strbuf_t *s, int increment) { /* Increment > 0: Linear buffer growth rate * Increment < -1: Exponential buffer growth rate */ if (increment == 0 || increment == -1){ NODE_ERR("BUG: Invalid string increment"); return -1; } s->increment = increment; return 0; }
static void net_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) { NODE_DBG("net_dns_found is called.\n"); struct espconn *pesp_conn = arg; if(pesp_conn == NULL){ NODE_DBG("pesp_conn null.\n"); return; } lnet_userdata *nud = (lnet_userdata *)pesp_conn->reverse; if(nud == NULL){ NODE_DBG("nud null.\n"); return; } if(nud->cb_dns_found_ref == LUA_NOREF){ NODE_DBG("cb_dns_found_ref null.\n"); return; } if(ipaddr == NULL) { NODE_ERR( "DNS Fail!\n" ); return; } // ipaddr->addr is a uint32_t ip char ip_str[20]; c_memset(ip_str, 0, sizeof(ip_str)); if(host_ip.addr == 0 && ipaddr->addr != 0) { c_sprintf(ip_str, IPSTR, IP2STR(&(ipaddr->addr))); } if(nud->self_ref == LUA_NOREF){ NODE_DBG("self_ref null.\n"); return; } lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->cb_dns_found_ref); // the callback function lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->self_ref); // pass the userdata(conn) to callback func in lua lua_pushstring(gL, ip_str); // the ip para lua_call(gL, 2, 0); if((pesp_conn->type == ESPCONN_TCP && pesp_conn->proto.tcp->remote_port == 0) || (pesp_conn->type == ESPCONN_UDP && pesp_conn->proto.udp->remote_port == 0) ){ lua_gc(gL, LUA_GCSTOP, 0); if(nud->self_ref != LUA_NOREF){ luaL_unref(gL, LUA_REGISTRYINDEX, nud->self_ref); nud->self_ref = LUA_NOREF; // unref this, and the net.socket userdata will delete it self } lua_gc(gL, LUA_GCRESTART, 0); } }
uint32_t platform_s_flash_read( void *to, uint32_t fromaddr, uint32_t size ) { fromaddr -= INTERNAL_FLASH_START_ADDRESS; SpiFlashOpResult r; WRITE_PERI_REG(0x60000914, 0x73); r = flash_read(fromaddr, (uint32 *)to, size); if(SPI_FLASH_RESULT_OK == r) return size; else{ NODE_ERR( "ERROR in flash_read: r=%d at %08X\n", ( int )r, ( unsigned )fromaddr+INTERNAL_FLASH_START_ADDRESS ); return 0; } }
static void socket_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) { NODE_DBG("enter socket_dns_found.\n"); struct espconn *pesp_conn = arg; if(pesp_conn == NULL){ NODE_DBG("pesp_conn null.\n"); return; } if(ipaddr == NULL) { dns_reconn_count++; if( dns_reconn_count >= 5 ){ NODE_ERR( "DNS Fail!\n" ); // Note: should delete the pesp_conn or unref self_ref here. mqtt_socket_disconnected(arg); // although not connected, but fire disconnect callback to release every thing. return; } NODE_ERR( "DNS retry %d!\n", dns_reconn_count ); host_ip.addr = 0; espconn_gethostbyname(pesp_conn, name, &host_ip, socket_dns_found); return; } // ipaddr->addr is a uint32_t ip if(ipaddr->addr != 0) { dns_reconn_count = 0; c_memcpy(pesp_conn->proto.tcp->remote_ip, &(ipaddr->addr), 4); NODE_DBG("TCP ip is set: "); NODE_DBG(IPSTR, IP2STR(&(ipaddr->addr))); NODE_DBG("\n"); socket_connect(pesp_conn); } NODE_DBG("leave socket_dns_found.\n"); }
strbuf_t *strbuf_new(int len) { strbuf_t *s; s = (strbuf_t *)cjson_mem_malloc(sizeof(strbuf_t)); if (!s){ NODE_ERR("not enough memory\n"); return NULL; } strbuf_init(s, len); /* Dynamic strbuf allocation / deallocation */ s->dynamic = 1; return s; }
/* * Assumptions: * > toaddr is INTERNAL_FLASH_WRITE_UNIT_SIZE aligned * > size is a multiple of INTERNAL_FLASH_WRITE_UNIT_SIZE */ uint32_t platform_s_flash_write( const void *from, uint32_t toaddr, uint32_t size ) { SpiFlashOpResult r; const uint32_t blkmask = INTERNAL_FLASH_WRITE_UNIT_SIZE - 1; uint32_t *apbuf = NULL; uint32_t fromaddr = (uint32_t)from; if( (fromaddr & blkmask ) || (fromaddr >= INTERNAL_FLASH_MAPPED_ADDRESS)) { apbuf = (uint32_t *)c_malloc(size); if(!apbuf) return 0; c_memcpy(apbuf, from, size); } system_soft_wdt_feed (); r = flash_write(toaddr, apbuf?(uint32 *)apbuf:(uint32 *)from, size); if(apbuf) c_free(apbuf); if(SPI_FLASH_RESULT_OK == r) return size; else{ NODE_ERR( "ERROR in flash_write: r=%d at %p\n", r, toaddr); return 0; } }
uint32_t platform_s_flash_write( const void *from, uint32_t toaddr, uint32_t size ) { toaddr -= INTERNAL_FLASH_START_ADDRESS; SpiFlashOpResult r; const uint32_t blkmask = INTERNAL_FLASH_WRITE_UNIT_SIZE - 1; uint32_t *apbuf = NULL; if( ((uint32_t)from) & blkmask ){ apbuf = (uint32_t *)c_malloc(size); if(!apbuf) return 0; c_memcpy(apbuf, from, size); } WRITE_PERI_REG(0x60000914, 0x73); r = flash_write(toaddr, apbuf?(uint32 *)apbuf:(uint32 *)from, size); if(apbuf) c_free(apbuf); if(SPI_FLASH_RESULT_OK == r) return size; else{ NODE_ERR( "ERROR in flash_write: r=%d at %08X\n", ( int )r, ( unsigned )toaddr+INTERNAL_FLASH_START_ADDRESS ); return 0; } }
void nodemcu_init(void) { NODE_ERR("\n"); // Initialize platform first for lua modules. if( platform_init() != PLATFORM_OK ) { // This should never happen NODE_DBG("Can not init platform for modules.\n"); return; } #if defined(FLASH_SAFE_API) if( flash_safe_get_size_byte() != flash_rom_get_size_byte()) { NODE_ERR("Self adjust flash size.\n"); // Fit hardware real flash size. flash_rom_set_size_byte(flash_safe_get_size_byte()); // Flash init data at FLASHSIZE - 0x04000 Byte. flash_init_data_default(); // Flash blank data at FLASHSIZE - 0x02000 Byte. flash_init_data_blank(); if( !fs_format() ) { NODE_ERR( "\ni*** ERROR ***: unable to format. FS might be compromised.\n" ); NODE_ERR( "It is advised to re-flash the NodeMCU image.\n" ); } else{ NODE_ERR( "format done.\n" ); } fs_unmount(); // mounted by format. } #endif // defined(FLASH_SAFE_API) if( !flash_init_data_written() ){ NODE_ERR("Restore init data.\n"); // Flash init data at FLASHSIZE - 0x04000 Byte. flash_init_data_default(); // Flash blank data at FLASHSIZE - 0x02000 Byte. flash_init_data_blank(); } #if defined( BUILD_WOFS ) romfs_init(); // if( !wofs_format() ) // { // NODE_ERR( "\ni*** ERROR ***: unable to erase the flash. WOFS might be compromised.\n" ); // NODE_ERR( "It is advised to re-flash the NodeWifi image.\n" ); // } // else // NODE_ERR( "format done.\n" ); // test_romfs(); #elif defined ( BUILD_SPIFFS ) fs_mount(); // test_spiffs(); #endif // endpoint_setup(); // char* lua_argv[] = { (char *)"lua", (char *)"-e", (char *)"print(collectgarbage'count');ttt={};for i=1,100 do table.insert(ttt,i*2 -1);print(i);end for k, v in pairs(ttt) do print('<'..k..' '..v..'>') end print(collectgarbage'count');", NULL }; // lua_main( 3, lua_argv ); // char* lua_argv[] = { (char *)"lua", (char *)"-i", NULL }; // lua_main( 2, lua_argv ); // char* lua_argv[] = { (char *)"lua", (char *)"-e", (char *)"pwm.setup(0,100,50) pwm.start(0) pwm.stop(0)", NULL }; // lua_main( 3, lua_argv ); // NODE_DBG("Flash sec num: 0x%x\n", flash_get_sec_num()); task_init(); system_os_post(USER_TASK_PRIO_0,SIG_LUA,'s'); }
static void ICACHE_FLASH_ATTR dnsQueryReceived(void *arg, char *data, unsigned short length) { // parse incoming query domain char domain[30]; char *writePos=domain; memset(domain,0,30); int offSet=12; int len=data[offSet]; while(len!=0 && offSet<length) { offSet++; memcpy(writePos,data+offSet,len); writePos+=len; //advance offSet+=len; len=data[offSet]; if(len!=0) { *writePos='.'; writePos++; } } DNS_DBG("DNS Query Received: %s",domain); if(!isKnownDNS(domain)) return; struct espconn *conn=arg; remot_info *premot = NULL; if (espconn_get_connection_info(conn,&premot,0) == ESPCONN_OK) { os_memcpy(conn->proto.udp->remote_ip, premot->remote_ip, 4); conn->proto.udp->remote_port = premot->remote_port; uint8_t *ip1 = conn->proto.udp->remote_ip; NODE_DBG("UDP:\nremote_ip: %d.%d.%d.%d remote_port: %d\n",ip4_addr1_16(ip1),ip4_addr2_16(ip1), ip4_addr3_16(ip1), ip4_addr4_16(ip1), premot->remote_port); } else { NODE_ERR("UDP: connection_info == NULL?\n"); } //build response char response[100] = {data[0], data[1], 0b10000100 | (0b00000001 & data[2]), //response, authorative answer, not truncated, copy the recursion bit 0b00000000, //no recursion available, no errors data[4], data[5], //Question count data[4], data[5], //answer count 0x00, 0x00, //NS record count 0x00, 0x00}; //Resource record count int idx = 12; memcpy(response+12, data+12, length-12); //Copy the rest of the query section idx += length-12; //Set a pointer to the domain name in the question section response[idx] = 0xC0; response[idx+1] = 0x0C; //Set the type to "Host Address" response[idx+2] = 0x00; response[idx+3] = 0x01; //Set the response class to IN response[idx+4] = 0x00; response[idx+5] = 0x01; //A 32 bit integer specifying TTL in seconds, 0 means no caching response[idx+6] = 0x00; response[idx+7] = 0x00; response[idx+8] = 0x00; response[idx+9] = 0x00; //RDATA length response[idx+10] = 0x00; response[idx+11] = 0x04; //4 byte IP address //The IP address response[idx + 12] = 192; response[idx + 13] = 168; response[idx + 14] = 4; response[idx + 15] = 1; int ret = espconn_send(conn, (uint8_t*)response, idx+16); uint8_t *ip = conn->proto.udp->local_ip; NODE_DBG("local_ip: %d.%d.%d.%d local_port: %d\n",ip4_addr1_16(ip),ip4_addr2_16(ip), ip4_addr3_16(ip), ip4_addr4_16(ip),conn->proto.udp->local_port); NODE_DBG("DNS reply sent\n"); }
static void net_server_connected(void *arg) // for tcp only { NODE_DBG("net_server_connected is called.\n"); struct espconn *pesp_conn = arg; int i = 0; lnet_userdata *skt = NULL; if(pesp_conn == NULL) return; #if 0 char temp[20] = {0}; c_sprintf(temp, IPSTR, IP2STR( &(pesp_conn->proto.tcp->remote_ip) ) ); NODE_DBG("remote "); NODE_DBG(temp); NODE_DBG(":"); NODE_DBG("%d",pesp_conn->proto.tcp->remote_port); NODE_DBG(" connected.\n"); #endif for(i=0;i<MAX_SOCKET;i++){ if(socket[i] == LUA_NOREF) // found empty slot { break; } } if(i>=MAX_SOCKET) // can't create more socket { NODE_ERR("MAX_SOCKET\n"); pesp_conn->reverse = NULL; // not accept this conn if(pesp_conn->proto.tcp->remote_port || pesp_conn->proto.tcp->local_port) espconn_disconnect(pesp_conn); return; } if(tcpserver_cb_connect_ref == LUA_NOREF) return; if(!gL) return; lua_rawgeti(gL, LUA_REGISTRYINDEX, tcpserver_cb_connect_ref); // get function // create a new client object skt = (lnet_userdata *)lua_newuserdata(gL, sizeof(lnet_userdata)); if(!skt){ NODE_ERR("can't newudata\n"); lua_pop(gL, 1); return; } // set its metatable luaL_getmetatable(gL, "net.socket"); lua_setmetatable(gL, -2); // pre-initialize it, in case of errors skt->self_ref = LUA_NOREF; lua_pushvalue(gL, -1); // copy the top of stack skt->self_ref = luaL_ref(gL, LUA_REGISTRYINDEX); // ref to it self, for module api to find the userdata socket[i] = skt->self_ref; // save to socket array socket_num++; skt->cb_connect_ref = LUA_NOREF; // this socket already connected skt->cb_reconnect_ref = LUA_NOREF; skt->cb_disconnect_ref = LUA_NOREF; skt->cb_receive_ref = LUA_NOREF; skt->cb_send_ref = LUA_NOREF; skt->cb_dns_found_ref = LUA_NOREF; #ifdef CLIENT_SSL_ENABLE skt->secure = 0; // as a server SSL is not supported. #endif skt->pesp_conn = pesp_conn; // point to the espconn made by low level sdk pesp_conn->reverse = skt; // let espcon carray the info of this userdata(net.socket) espconn_regist_recvcb(pesp_conn, net_socket_received); espconn_regist_sentcb(pesp_conn, net_socket_sent); espconn_regist_disconcb(pesp_conn, net_server_disconnected); espconn_regist_reconcb(pesp_conn, net_server_reconnected); // now socket[i] has the client ref, and stack top has the userdata lua_call(gL, 1, 0); // function(conn) }
//rc.send(0,267715,24,185,1) --GPIO, code, bits, pulselen, protocol static int ICACHE_FLASH_ATTR rc_send(lua_State* L) { const uint8_t pin = luaL_checkinteger(L, 1); platform_gpio_mode(pin, PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_FLOAT); //platform_gpio_mode(pin, PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_PULLUP); //platform_gpio_mode(pin, PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_PULLDOWN); platform_gpio_write(pin, 0); long code = luaL_checklong(L, 2); //const uint8_t bits = luaL_checkinteger(L, 3); uint8_t bits = luaL_checkinteger(L, 3); const uint8_t pulseLen = luaL_checkinteger(L, 4); const uint8_t Protocol = luaL_checkinteger(L, 5); const uint8_t repeat = luaL_checkinteger(L, 6); NODE_ERR("pulseLen:%d\n",pulseLen); NODE_ERR("Protocol:%d\n",Protocol); NODE_ERR("repeat:%d\n",repeat); NODE_ERR("send:"); int c,k,nRepeat; bits = bits-1; for (c = bits; c >= 0; c--) { k = code >> c; if (k & 1) NODE_ERR("1"); else NODE_ERR("0"); } NODE_ERR("\n"); for (nRepeat=0; nRepeat<repeat; nRepeat++) { for (c = bits; c >= 0; c--) { k = code >> c; if (k & 1){ //send1 if(Protocol==1){ transmit(pin,pulseLen,3,1); }else if(Protocol==2){ transmit(pin,pulseLen,2,1); }else if(Protocol==3){ transmit(pin,pulseLen,9,6); } } else{ //send0 if(Protocol==1){ transmit(pin,pulseLen,1,3); }else if(Protocol==2){ transmit(pin,pulseLen,1,2); }else if(Protocol==3){ transmit(pin,pulseLen,4,11); } } } //sendSync(); if(Protocol==1){ transmit(pin,pulseLen,1,31); }else if(Protocol==2){ transmit(pin,pulseLen,1,10); }else if(Protocol==3){ transmit(pin,pulseLen,1,71); } } return 1; }
//Cgi that check the request has the correct HOST header //Using it we can ensure our server has a domain of our choice int cgi_check_host(http_connection *connData) { http_server_config *config = (http_server_config*)connData->cgi.argument; if(config==NULL) return HTTPD_CGI_NEXT_RULE; if(config->host_domain==NULL) return HTTPD_CGI_NEXT_RULE; if(connData->state==HTTPD_STATE_ON_URL) { http_set_save_header(connData,HTTP_HOST); return HTTPD_CGI_NEXT_RULE; } if(connData->state==HTTPD_STATE_HEADERS_END) { header *hostHeader = http_get_header(connData,HTTP_HOST); if(hostHeader==NULL) { NODE_ERR("Host header not found\n"); http_response_BAD_REQUEST(connData); return HTTPD_CGI_DONE; } const char * domain = config->host_domain; HTTP_CGI_DBG("Host header: %s, domain: %s\n",hostHeader->value,domain); if(strncmp(hostHeader->value,domain,strlen(domain))==0) //compare ignoring http:// and last / { HTTP_CGI_DBG("Domain match\n"); return HTTPD_CGI_NEXT_RULE; } else{ uint8_t op = wifi_get_opmode(); char ipaddrstr[17]; os_bzero(ipaddrstr, sizeof(ipaddrstr)); struct ip_info ipConfig; switch (op) { case STATIONAP_MODE: { wifi_get_ip_info(SOFTAP_IF,&ipConfig); //0x01 ipaddr_ntoa_r(&ipConfig.ip,ipaddrstr, sizeof(ipaddrstr)); if(strncmp(hostHeader->value,ipaddrstr,strlen(ipaddrstr))==0) { HTTP_CGI_DBG("SoftAp ip match"); return HTTPD_CGI_NEXT_RULE; } } case STATION_MODE: { os_bzero(ipaddrstr, sizeof(ipaddrstr)); wifi_get_ip_info(STATION_IF,&ipConfig); //0x00 ipaddr_ntoa_r(&ipConfig.ip,ipaddrstr, sizeof(ipaddrstr)); if(strncmp(hostHeader->value,ipaddrstr,strlen(ipaddrstr))==0) { HTTP_CGI_DBG("Station ip match"); return HTTPD_CGI_NEXT_RULE; } } } HTTP_CGI_DBG("Hosts don't match\n"); if(config->enable_captive) { //to enable a captive portal we should redirect here char * redirectUrl = (char *)os_zalloc(strlen(domain)+9); // domain length + http:// + / + \0 strcpy(redirectUrl,"http://"); os_strcat(redirectUrl,domain); os_strcat(redirectUrl,"/"); http_response_REDIRECT(connData, redirectUrl); os_free(redirectUrl); HTTP_CGI_DBG("Redirect URL = %s\n", redirectUrl); } else { //bad request else http_response_BAD_REQUEST(connData); } return HTTPD_CGI_DONE; } } return HTTPD_CGI_NEXT_RULE; }