/****************************************************************************** * FunctionName : espconn_tcp_delete * Description : delete the server: delete a listening PCB and free it * Parameters : pdeletecon -- the espconn used to delete a server * Returns : none *******************************************************************************/ sint8 ICACHE_FLASH_ATTR espconn_tcp_delete(struct espconn *pdeletecon) { err_t err; remot_info *pinfo = NULL; espconn_msg *pdelete_msg = NULL; struct tcp_pcb *pcb = NULL; if (pdeletecon == NULL) return ESPCONN_ARG; espconn_get_connection_info(pdeletecon, &pinfo , 0); if (pdeletecon->link_cnt != 0) return ESPCONN_INPROGRESS; else { os_printf("espconn_tcp_delete %p\n",pdeletecon); pdelete_msg = pserver_list; while (pdelete_msg != NULL){ if (pdelete_msg->pespconn == pdeletecon){ /*remove the node from the client's active connection list*/ espconn_list_delete(&pserver_list, pdelete_msg); pcb = pdelete_msg->preverse; os_printf("espconn_tcp_delete %d\n",pcb->state); err = tcp_close(pcb); os_free(pdelete_msg); pdelete_msg = NULL; break; } pdelete_msg = pdelete_msg->pnext; } if (err == ERR_OK) return err; else return ESPCONN_ARG; } }
static void ICACHE_FLASH_ATTR incoming_connection_callback(void *arg) { struct espconn *pconnection = arg; remot_info *premot = NULL; uint8_t idx; int8_t value; espconn_regist_recvcb(pconnection, tcpserver_recv_callback); espconn_regist_reconcb(pconnection, tcpserver_reconnect_callback); espconn_regist_disconcb(pconnection, tcpserver_disconnect_callback); value = espconn_get_connection_info(&tcp_server, &premot, 0); os_printf("Incoming TCP connection. link_cnt=%d. Get connnection info result:[%d]\r\n", tcp_server.link_cnt, value); if (value == ESPCONN_OK) { //char *testString = "Hello! This is a TCP server on ESP8266.\r\n"; for (idx = 0; idx < tcp_server.link_cnt; idx++) { os_printf("TCP client %d: %d.%d.%d.%d:%d\r\n", idx + 1, premot[idx].remote_ip[0], premot[idx].remote_ip[1], premot[idx].remote_ip[2], premot[idx].remote_ip[3], premot[idx].remote_port); } } os_printf("\r\n"); }
/****************************************************************************** * FunctionName : espconn_tcp_accept * Description : A new incoming connection has been accepted. * Parameters : arg -- Additional argument to pass to the callback function * pcb -- The connection pcb which is accepted * err -- An unused error code, always ERR_OK currently * Returns : acception result *******************************************************************************/ static err_t ICACHE_FLASH_ATTR espconn_tcp_accept(void *arg, struct tcp_pcb *pcb, err_t err) { struct espconn *espconn = arg; espconn_msg *paccept = NULL; remot_info *pinfo = NULL; LWIP_UNUSED_ARG(err); if(system_get_free_heap_size() < 8192) return ERR_MEM; // added PV` paccept = (espconn_msg *)os_zalloc(sizeof(espconn_msg)); tcp_arg(pcb, paccept); tcp_err(pcb, esponn_server_err); if (paccept == NULL) return ERR_MEM; /*insert the node to the active connection list*/ espconn_list_creat(&plink_active, paccept); paccept->preverse = espconn; paccept->pespconn = (struct espconn *)os_zalloc(sizeof(struct espconn)); if (paccept->pespconn == NULL) return ERR_MEM; paccept->pespconn->proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp)); if (paccept->pespconn->proto.tcp == NULL) return ERR_MEM; //paccept->pcommon.timeout = 0x0a; //link_timer = 0x0a; paccept->pcommon.pcb = pcb; paccept->pcommon.remote_port = pcb->remote_port; paccept->pcommon.remote_ip[0] = ip4_addr1_16(&pcb->remote_ip); paccept->pcommon.remote_ip[1] = ip4_addr2_16(&pcb->remote_ip); paccept->pcommon.remote_ip[2] = ip4_addr3_16(&pcb->remote_ip); paccept->pcommon.remote_ip[3] = ip4_addr4_16(&pcb->remote_ip); os_memcpy(espconn->proto.tcp->remote_ip, paccept->pcommon.remote_ip, 4); espconn->proto.tcp->remote_port = pcb->remote_port; espconn->state = ESPCONN_CONNECT; espconn_copy_partial(paccept->pespconn, espconn); espconn_get_connection_info(espconn, &pinfo , 0); espconn_printf("espconn_tcp_accept link_cnt: %d\n", espconn->link_cnt); if (espconn->link_cnt == espconn_tcp_get_max_con_allow(espconn) + 1) return ERR_ISCONN; tcp_sent(pcb, espconn_server_sent); tcp_recv(pcb, espconn_server_recv); tcp_poll(pcb, espconn_server_poll, 8); /* every 1 seconds */ if (paccept->pespconn->proto.tcp->connect_callback != NULL) { paccept->pespconn->proto.tcp->connect_callback(paccept->pespconn); } return ERR_OK; }
static void ICACHE_FLASH_ATTR tcpserver_recv_callback(void *arg, char *pdata, uint16_t length) { if(os_strncmp(OTA_UPGRADE_COMMAND, pdata, length) == 0) { remot_info *phost_info = NULL; os_printf("Upgrade command received.\r\n"); espconn_get_connection_info(&tcp_server, &phost_info, 0); ota_upgrade(phost_info); } }
static void ICACHE_FLASH_ATTR udp_received(void *arg, char *data, unsigned short len) { struct espconn *udpconn= (struct espconn*)arg; if (len > 5 && strncmp(data, "HAP", 3) == 0) { const char* hapServer = &data[5]; if (strcmp(settings.serverName, hapServer) != 0) return; remot_info *info = NULL; espconn_get_connection_info(udpconn, &info, 0); uint16_t port = (data[3] << 8) | data[4]; uint32_t address = *(uint32_t*)info->remote_ip; if (port == hapPort && address == hapAddress) return; hapAddress = address; hapPort = port; static bool inited = false; DEBUG_PRINT("[HAP]Discover from "IPSTR":%d\n", IP2STR(&address), port); if (inited) { MQTT_Disconnect(&mqttClient); DEBUG_PRINT("[HAP]Disconnect MQTT\n"); } char aux[20]; os_sprintf(aux, IPSTR, IP2STR(&address)); MQTT_InitConnection(&mqttClient, aux, hapPort); os_sprintf(aux, "client_%d", system_get_chip_id()); MQTT_InitClient(&mqttClient, aux, settings.mqttUser, settings.mqttPassword, MQTT_KEEPALIVE, 1); MQTT_OnConnected(&mqttClient, mqttConnectedCb); MQTT_OnDisconnected(&mqttClient, mqttDisconnectedCb); MQTT_OnPublished(&mqttClient, mqttPublishedCb); MQTT_OnData(&mqttClient, mqttDataCb); MQTT_Connect(&mqttClient); inited = true; } }
LOCAL void ICACHE_FLASH_ATTR airkiss_wifilan_recv_callbk(void *arg, char *pdata, unsigned short len) { uint16 i; remot_info* pcon_info = NULL; airkiss_lan_ret_t ret = airkiss_lan_recv(pdata, len, &akconf); airkiss_lan_ret_t packret; switch (ret){ case AIRKISS_LAN_SSDP_REQ: espconn_get_connection_info(&pssdpudpconn, &pcon_info, 0); os_printf("remote ip: %d.%d.%d.%d \r\n",pcon_info->remote_ip[0],pcon_info->remote_ip[1], pcon_info->remote_ip[2],pcon_info->remote_ip[3]); os_printf("remote port: %d \r\n",pcon_info->remote_port); pssdpudpconn.proto.udp->remote_port = pcon_info->remote_port; memcpy(pssdpudpconn.proto.udp->remote_ip,pcon_info->remote_ip,4); ssdp_udp.remote_port = DEFAULT_LAN_PORT; lan_buf_len = sizeof(lan_buf); packret = airkiss_lan_pack(AIRKISS_LAN_SSDP_RESP_CMD, DEVICE_TYPE, DEVICE_ID, 0, 0, lan_buf, &lan_buf_len, &akconf); if (packret != AIRKISS_LAN_PAKE_READY) { os_printf("Pack lan packet error!"); return; } os_printf("\r\n\r\n"); for (i=0; i<lan_buf_len; i++) os_printf("%c",lan_buf[i]); os_printf("\r\n\r\n"); packret = espconn_sendto(&pssdpudpconn, lan_buf, lan_buf_len); if (packret != 0) { os_printf("LAN UDP Send err!"); } break; default: os_printf("Pack is not ssdq req!%d\r\n",ret); break; } }
/****************************************************************************** * FunctionName : espconn_tcp_accept * Description : A new incoming connection has been accepted. * Parameters : arg -- Additional argument to pass to the callback function * pcb -- The connection pcb which is accepted * err -- An unused error code, always ERR_OK currently * Returns : acception result *******************************************************************************/ static err_t ICACHE_FLASH_ATTR espconn_tcp_accept(void *arg, struct tcp_pcb *pcb, err_t err) { struct espconn *espconn = arg; espconn_msg *paccept = NULL; remot_info *pinfo = NULL; LWIP_UNUSED_ARG(err); if (!espconn || !espconn->proto.tcp) { return ERR_ARG; } tcp_arg(pcb, paccept); tcp_err(pcb, esponn_server_err); /*Ensure the active connection is less than the count of active connections on the server*/ espconn_get_connection_info(espconn, &pinfo , 0); espconn_printf("espconn_tcp_accept link_cnt: %d\n", espconn->link_cnt); if (espconn->link_cnt == espconn_tcp_get_max_con_allow(espconn)) return ERR_ISCONN; /*Creates a new active connect control message*/ paccept = (espconn_msg *)malloc(sizeof(espconn_msg)); memset(paccept, 0, sizeof(espconn_msg)); tcp_arg(pcb, paccept); if (paccept == NULL) return ERR_MEM; /*Insert the node to the active connection list*/ espconn_list_creat(&plink_active, paccept); paccept->preverse = espconn; paccept->pespconn = (struct espconn *)malloc(sizeof(struct espconn)); if (paccept->pespconn == NULL) return ERR_MEM; paccept->pespconn->proto.tcp = (esp_tcp *)malloc(sizeof(esp_tcp)); if (paccept->pespconn->proto.tcp == NULL) return ERR_MEM; /*Reserve the remote information for current active connection*/ paccept->pcommon.pcb = pcb; paccept->pcommon.remote_port = pcb->remote_port; paccept->pcommon.remote_ip[0] = ip4_addr1_16(&pcb->remote_ip.u_addr.ip4); paccept->pcommon.remote_ip[1] = ip4_addr2_16(&pcb->remote_ip.u_addr.ip4); paccept->pcommon.remote_ip[2] = ip4_addr3_16(&pcb->remote_ip.u_addr.ip4); paccept->pcommon.remote_ip[3] = ip4_addr4_16(&pcb->remote_ip.u_addr.ip4); paccept->pcommon.write_flag = true; memcpy(espconn->proto.tcp->remote_ip, paccept->pcommon.remote_ip, 4); espconn->proto.tcp->remote_port = pcb->remote_port; espconn->state = ESPCONN_CONNECT; espconn_copy_partial(paccept->pespconn, espconn); /*Set the specify function that should be called * when TCP data has been successfully delivered, * when active connection receives data, * or periodically from active connection*/ tcp_sent(pcb, espconn_server_sent); tcp_recv(pcb, espconn_server_recv); tcp_poll(pcb, espconn_server_poll, 8); /* every 1 seconds */ /*Disable Nagle algorithm default*/ tcp_nagle_disable(pcb); /*Default set the total number of espconn_buf on the unsent lists for one*/ espconn_tcp_set_buf_count(paccept->pespconn, 1); if (paccept->pespconn->proto.tcp->connect_callback != NULL) { paccept->pespconn->proto.tcp->connect_callback(paccept->pespconn); } /*Enable keep alive option*/ if (espconn_keepalive_disabled(paccept)) espconn_keepalive_enable(pcb); return ERR_OK; }
/****************************************************************************** * FunctionName : user_devicefind_recv * Description : Processing the received data from the host * Parameters : arg -- Additional argument to pass to the callback function * pusrdata -- The received data (or NULL when the connection has been closed!) * length -- The length of received data * Returns : none *******************************************************************************/ LOCAL void ICACHE_FLASH_ATTR user_devicefind_recv(void *arg, char *pusrdata, unsigned short length) { char DeviceBuffer[40] = {0}; char Device_mac_buffer[60] = {0}; char hwaddr[6]; struct ip_info ipconfig; if (wifi_get_opmode() != STATION_MODE) { wifi_get_ip_info(SOFTAP_IF, &ipconfig); wifi_get_macaddr(SOFTAP_IF, hwaddr); if (!ip_addr_netcmp((struct ip_addr *)ptrespconn.proto.udp->remote_ip, &ipconfig.ip, &ipconfig.netmask)) { wifi_get_ip_info(STATION_IF, &ipconfig); wifi_get_macaddr(STATION_IF, hwaddr); } } else { wifi_get_ip_info(STATION_IF, &ipconfig); wifi_get_macaddr(STATION_IF, hwaddr); } if (pusrdata == NULL) { return; } if (length == os_strlen(device_find_request) && os_strncmp(pusrdata, device_find_request, os_strlen(device_find_request)) == 0) { length = os_sprintf(DeviceBuffer, "%s" MACSTR " " IPSTR, device_find_response_ok, MAC2STR(hwaddr), IP2STR(&ipconfig.ip)); DF_DBG("%s\n", DeviceBuffer); //length = os_strlen(DeviceBuffer); //================================== //This is add in sdk lib v1.4.0 DF_DBG("--------DEBUG IN DEV----------\r\n"); remote_info* pcon_info = NULL; DF_DBG("link num: %d \r\n",ptrespconn.link_cnt); espconn_get_connection_info(&ptrespconn, &pcon_info, 0); DF_DBG("remote ip: %d.%d.%d.%d \r\n",pcon_info->remote_ip[0],pcon_info->remote_ip[1], pcon_info->remote_ip[2],pcon_info->remote_ip[3]); DF_DBG("remote port: %d \r\n",pcon_info->remote_port); //================================= ptrespconn.proto.udp->remote_port = pcon_info->remote_port; os_memcpy(ptrespconn.proto.udp->remote_ip,pcon_info->remote_ip,4); espconn_sendto(&ptrespconn, DeviceBuffer, length); } else if (length == (os_strlen(device_find_request) + 18)) { os_sprintf(Device_mac_buffer, "%s " MACSTR , device_find_request, MAC2STR(hwaddr)); DF_DBG("%s", Device_mac_buffer); if (os_strncmp(Device_mac_buffer, pusrdata, os_strlen(device_find_request) + 18) == 0) { length = os_sprintf(DeviceBuffer, "%s" MACSTR " " IPSTR, device_find_response_ok,MAC2STR(hwaddr), IP2STR(&ipconfig.ip)); DF_DBG("%s\n", DeviceBuffer); espconn_sendto(&ptrespconn, DeviceBuffer, length); } else { return; } } }
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"); }
/****************************************************************************** * FunctionName : user_devicefind_recv * Description : Processing the received data from the host * Parameters : arg -- Additional argument to pass to the callback function * pusrdata -- The received data (or NULL when the connection has been closed!) * length -- The length of received data * Returns : none *******************************************************************************/ LOCAL void ICACHE_FLASH_ATTR user_devicefind_recv(void *arg, char *pusrdata, unsigned short length) { os_printf("1-----------\n"); char DeviceBuffer[40] = {0}; char Device_mac_buffer[60] = {0}; char hwaddr[6]; remot_info *premot = NULL; struct ip_info ipconfig; if (wifi_get_opmode() != STATION_MODE) { wifi_get_ip_info(SOFTAP_IF, &ipconfig); wifi_get_macaddr(SOFTAP_IF, hwaddr); if (!ip_addr_netcmp((struct ip_addr *)ptrespconn.proto.udp->remote_ip, &ipconfig.ip, &ipconfig.netmask)) { wifi_get_ip_info(STATION_IF, &ipconfig); wifi_get_macaddr(STATION_IF, hwaddr); } } else { wifi_get_ip_info(STATION_IF, &ipconfig); wifi_get_macaddr(STATION_IF, hwaddr); } if (pusrdata == NULL) { return; } if (length == os_strlen(device_find_request) && os_strncmp(pusrdata, device_find_request, os_strlen(device_find_request)) == 0) { os_sprintf(DeviceBuffer, "%s" MACSTR " " IPSTR, device_find_response_ok, MAC2STR(hwaddr), IP2STR(&ipconfig.ip)); os_printf("%s\n", DeviceBuffer); length = os_strlen(DeviceBuffer); if (espconn_get_connection_info(&ptrespconn, &premot, 0) != ESPCONN_OK) return; os_memcpy(ptrespconn.proto.udp->remote_ip, premot->remote_ip, 4); ptrespconn.proto.udp->remote_port = premot->remote_port; espconn_sent(&ptrespconn, DeviceBuffer, length); } else if (length == (os_strlen(device_find_request) + 18)) { os_sprintf(Device_mac_buffer, "%s " MACSTR , device_find_request, MAC2STR(hwaddr)); os_printf("%s", Device_mac_buffer); if (os_strncmp(Device_mac_buffer, pusrdata, os_strlen(device_find_request) + 18) == 0) { //os_printf("%s\n", Device_mac_buffer); length = os_strlen(DeviceBuffer); os_sprintf(DeviceBuffer, "%s" MACSTR " " IPSTR, device_find_response_ok, MAC2STR(hwaddr), IP2STR(&ipconfig.ip)); os_printf("%s\n", DeviceBuffer); length = os_strlen(DeviceBuffer); if (espconn_get_connection_info(&ptrespconn, &premot, 0) != ESPCONN_OK) return; os_memcpy(ptrespconn.proto.udp->remote_ip, premot->remote_ip, 4); ptrespconn.proto.udp->remote_port = premot->remote_port; espconn_sent(&ptrespconn, DeviceBuffer, length); } else { return; } } }
// Lua: server/socket:send( string, function(sent) ) static int net_send( lua_State* L, const char* mt ) { // NODE_DBG("net_send is called.\n"); bool isserver = false; struct espconn *pesp_conn = NULL; lnet_userdata *nud; size_t l; nud = (lnet_userdata *)luaL_checkudata(L, 1, mt); luaL_argcheck(L, nud, 1, "Server/Socket expected"); if(nud==NULL){ NODE_DBG("userdata is nil.\n"); return 0; } if(nud->pesp_conn == NULL){ NODE_DBG("nud->pesp_conn is NULL.\n"); return 0; } pesp_conn = nud->pesp_conn; if (mt!=NULL && c_strcmp(mt, "net.server")==0) isserver = true; else if (mt!=NULL && c_strcmp(mt, "net.socket")==0) isserver = false; else { NODE_DBG("wrong metatable for net_send.\n"); return 0; } if(isserver && nud->pesp_conn->type == ESPCONN_TCP){ return luaL_error( L, "tcp server send not supported" ); } #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(" sending data.\n"); #endif const char *payload = luaL_checklstring( L, 2, &l ); if (l>1460 || payload == NULL) return luaL_error( L, "need <1460 payload" ); if (lua_type(L, 3) == LUA_TFUNCTION || lua_type(L, 3) == LUA_TLIGHTFUNCTION){ lua_pushvalue(L, 3); // copy argument (func) to the top of stack if(nud->cb_send_ref != LUA_NOREF) luaL_unref(L, LUA_REGISTRYINDEX, nud->cb_send_ref); nud->cb_send_ref = luaL_ref(L, LUA_REGISTRYINDEX); } // SDK 1.4.0 changed behaviour, for UDP server need to look up remote ip/port if (isserver && pesp_conn->type == ESPCONN_UDP) { remot_info *pr = 0; if (espconn_get_connection_info (pesp_conn, &pr, 0) != ESPCONN_OK) return luaL_error (L, "remote ip/port unavailable"); pesp_conn->proto.udp->remote_port = pr->remote_port; os_memmove (pesp_conn->proto.udp->remote_ip, pr->remote_ip, 4); // The remot_info apparently should *not* be os_free()d, fyi } #ifdef CLIENT_SSL_ENABLE if(nud->secure) espconn_secure_sent(pesp_conn, (unsigned char *)payload, l); else #endif espconn_sent(pesp_conn, (unsigned char *)payload, l); return 0; }