/** * Close a socket. */ void net_ESP8266_BOARD_closeSocket( JsNetwork *net, //!< The Network we are going to use to create the socket. int socketId //!< The socket to be closed. ) { os_printf("> net_ESP8266_BOARD_closeSocket, socket=%d\n", socketId); struct socketData *pSocketData = getSocketData(socketId); assert(pSocketData != NULL); assert(pSocketData->state != SOCKET_STATE_UNUSED); // Shouldn't be closing an unused socket. dumpEspConn(pSocketData->pEspconn); esp8266_dumpSocket(socketId); // How we close the socket is a function of what kind of socket it is. if (pSocketData->creationType == SOCKET_CREATED_SERVER) { int rc = espconn_delete(pSocketData->pEspconn); if (rc != 0) { os_printf("espconn_delete: rc=%d\n", rc); } } // End this is a server socket else { if (pSocketData->state == SOCKET_STATE_IDLE || pSocketData->state == SOCKET_STATE_CLOSING) { doClose(socketId); } else { pSocketData->shouldClose = true; } } // End this is a client socket }
static void ICACHE_FLASH_ATTR ntp_udp_recv(void *arg, char *pdata, unsigned short len) { struct tm *dt; time_t timestamp; ntp_t *ntp; os_timer_disarm(&ntp_timeout); // extract ntp time ntp = (ntp_t*)pdata; timestamp = ntp->trans_time[0] << 24 | ntp->trans_time[1] << 16 |ntp->trans_time[2] << 8 | ntp->trans_time[3]; // convert to unix time timestamp -= 2208988800UL; // create tm struct dt = gmtime(×tamp); // do something with it, like setting an rtc //ds1307_setTime(dt); // or just print it out char timestr[11]; os_sprintf(timestr, "%02d:%02d:%02d\r\n", dt->tm_hour, dt->tm_min, dt->tm_sec); uart0_tx_buffer(timestr, 10); // clean up connection if (pCon) { espconn_delete(pCon); os_free(pCon->proto.udp); os_free(pCon); pCon = 0; } }
// method socket.__del__() STATIC mp_obj_t esp_socket___del__(mp_obj_t self_in) { esp_socket_obj_t *s = self_in; esp_socket_close(self_in); if (s->fromserver) { espconn_delete(s->espconn); } return mp_const_none; }
void ICACHE_FLASH_ATTR esp8266_destroyConnection(NetConnection* conn) { if(conn->driverData) { HTTPESP8266ConnectionData* connData = (HTTPESP8266ConnectionData*)conn->driverData; espconn_delete(&connData->connection); if(connData->connection.proto.tcp) os_free(connData->connection.proto.tcp); os_free(connData); conn->driverData = NULL; } }
/** * @brief Delete tcp client and free all memory * @param mqttClient: The mqtt client which contain TCP client * @retval None */ void ICACHE_FLASH_ATTR mqtt_tcpclient_delete(MQTT_Client *mqttClient) { if (mqttClient->pCon != NULL) { INFO("Free memory\r\n"); espconn_delete(mqttClient->pCon); if (mqttClient->pCon->proto.tcp) os_free(mqttClient->pCon->proto.tcp); os_free(mqttClient->pCon); mqttClient->pCon = NULL; } }
static void ICACHE_FLASH_ATTR ntp_udp_timeout(void *arg) { os_timer_disarm(&ntp_timeout); uart0_tx_buffer("ntp timout\r\n", 12); // clean up connection if (pCon) { espconn_delete(pCon); os_free(pCon->proto.udp); os_free(pCon); pCon = 0; } }
/** * @brief Execution commad of close ip link. * @param id: commad id number * @retval None */ void ICACHE_FLASH_ATTR at_exeCmdCipclose(uint8_t id) { char temp[64]; // if(mdState == m_linked) // { // // } if(at_ipMux) { uart0_sendStr("MUX=1\r\n"); return; } if(pLink[0].linkEn) { if(serverEn) { /* restart */ uart0_sendStr("we must restart\r\n"); return; } else { if(pLink[0].pCon->type == ESPCONN_TCP) { specialAtState = FALSE; espconn_disconnect(pLink[0].pCon); } else { pLink[0].linkEn = FALSE; espconn_delete(pLink[0].pCon); os_free(pLink[0].pCon->proto.udp); os_free(pLink[0].pCon); at_linkNum--; if(at_linkNum == 0) { mdState = m_unlink; at_backOk; uart0_sendStr("Unlink\r\n"); } } } } else { at_backError; } }
/** * Perform an actual closure of the socket by calling the ESP8266 disconnect API. */ static void doClose( struct socketData *pSocketData //!< The socket to be closed. ) { if (pSocketData == NULL) return; // just in case // if we're already closing, then don't do anything if (pSocketData->state == SOCKET_STATE_CLOSED || pSocketData->state == SOCKET_STATE_DISCONNECTING) { return; } // if we're in the name resolution phase, we don't have much to do // if we're in aborting ditto if (pSocketData->state == SOCKET_STATE_HOST_RESOLVING || pSocketData->state == SOCKET_STATE_ABORTING) { pSocketData->state = SOCKET_STATE_DISCONNECTING; return; } // if we need to abort, then do that if (pSocketData->state == SOCKET_STATE_TO_ABORT) { espconn_abort(pSocketData->pEspconn); pSocketData->state = SOCKET_STATE_DISCONNECTING; return; } // Tell espconn to disconnect/delete the connection if (pSocketData->creationType == SOCKET_CREATED_SERVER) { //dumpEspConn(pSocketData->pEspconn); int rc = espconn_delete(pSocketData->pEspconn); if (rc != 0) { setSocketInError(pSocketData, rc); } // FIXME: do we get a disconnected callback or is this it? If we don't get a callback we can // go straight to SOCKET_STATE_CLOSED pSocketData->state = SOCKET_STATE_DISCONNECTING; } else { int rc = espconn_disconnect(pSocketData->pEspconn); if (rc == 0) { pSocketData->state = SOCKET_STATE_DISCONNECTING; } else { setSocketInError(pSocketData, rc); pSocketData->state = SOCKET_STATE_CLOSED; // don't expect a callback } } }
/** * @brief Delete tcp client and free all memory * @param mqttClient: The mqtt client which contain TCP client * @retval None */ void ICACHE_FLASH_ATTR mqtt_tcpclient_delete(MQTT_Client * mqttClient) { if (mqttClient->pCon != NULL) { MQTT_INFO("TCP: Free memory\r\n"); // Force abort connections espconn_abort(mqttClient->pCon); // Delete connections espconn_delete(mqttClient->pCon); if (mqttClient->pCon->proto.tcp) { os_free(mqttClient->pCon->proto.tcp); mqttClient->pCon->proto.tcp = NULL; } os_free(mqttClient->pCon); mqttClient->pCon = NULL; } }
void ICACHE_FLASH_ATTR serverDeInit(void) { espconn_disconnect(serverConn); DBG_MSG("espconn_disconnect\r\n"); espconn_delete(serverConn); DBG_MSG("espconn_delete\r\n"); if (serverConn != NULL) os_free(serverConn); DBG_MSG("os_free(serverConn)\r\n"); if (serverTcp != NULL) os_free(serverTcp); DBG_MSG("os_free(serverTcp)\r\n"); if (connData != NULL) os_free(connData); DBG_MSG("os_free(connData)\r\n"); if (txbuffer != NULL) os_free(txbuffer); DBG_MSG("os_free(txbuffer)\r\n"); if (rxbuffer != NULL) os_free(rxbuffer); DBG_MSG("os_free(rxbuffer)\r\n"); }
void ICACHE_FLASH_ATTR http_ws_server_init(http_callback connect,http_callback disconnect,http_callback received,http_callback data_sent) { app_callback = received; data_sent_callback=data_sent; client_disconnected_callback = disconnect; client_connected_callback = connect; espconn_delete(&ws_config.server_conn); //just to be sure we are on square 1 ws_config.server_conn.type = ESPCONN_TCP; ws_config.server_conn.state = ESPCONN_NONE; ws_config.server_conn.proto.tcp = &ws_config.server_tcp; ws_config.server_conn.proto.tcp->local_port = WS_PORT; NODE_DBG("Websocket server init, conn=%p", &ws_config.server_conn); }
bool ESP8266Client::disconnect() { sint8 res = ESPCONN_OK; m_bIsConnecting = false; if (isTcp()) { res = espconn_disconnect(esp_conn); } else { espconn_delete(esp_conn); m_bIsConnected = false; } if (res != ESPCONN_OK) { error("could not disconnect: ", res); } return res == ESPCONN_OK; }
void ICACHE_FLASH_ATTR wifiConnectCb(uint8_t status) { if(status == STATION_GOT_IP){ INFO("Wifi connection established\n"); udp_server = (struct espconn *) os_zalloc(sizeof(struct espconn)); udp_server->type = ESPCONN_UDP; udp_server->proto.udp = (esp_udp *) os_zalloc(sizeof(esp_udp)); udp_server->proto.udp->local_port = udp_port; espconn_regist_recvcb(udp_server, udpserver_recv); espconn_create(udp_server); system_os_post(DMX_TASK_PRIO, 0, 0); } else if(udp_server != NULL) { espconn_delete(udp_server); os_free(udp_server); udp_server = NULL; } }
void ICACHE_FLASH_ATTR init_dns() { //set softAP DHCP server router info uint8_t mode = 1; wifi_softap_set_dhcps_offer_option(OFFER_ROUTER, &mode); //1:station; 2:soft-AP, 3:station+soft-AP wifi_set_broadcast_if(3); // espconn_disconnect(&dnsConn); espconn_delete(&dnsConn); dnsConn.type=ESPCONN_UDP; dnsConn.state=ESPCONN_NONE; dnsUdp.local_port= 53; dnsConn.proto.udp=&dnsUdp; espconn_regist_recvcb(&dnsConn, dnsQueryReceived); int res = espconn_create(&dnsConn); NODE_DBG("DNS server init, conn=%p , status=%d", &dnsConn,res); }
static void ICACHE_FLASH_ATTR wifi_event_handler(System_Event_t *e) { switch (e->event) { case EVENT_STAMODE_CONNECTED: espconn_accept(&s_server_conn); espconn_regist_recvcb(&s_server_conn, espconn_recv_handler); break; case EVENT_STAMODE_DISCONNECTED: espconn_delete(&s_server_conn); break; case EVENT_STAMODE_GOT_IP: case EVENT_STAMODE_DHCP_TIMEOUT: case EVENT_STAMODE_AUTHMODE_CHANGE: case EVENT_SOFTAPMODE_STACONNECTED: case EVENT_SOFTAPMODE_STADISCONNECTED: case EVENT_SOFTAPMODE_PROBEREQRECVED: default: break; } }
static void FUNCTION_ATTRIBUTE free_conn(void) { PRINTF("free conn\n"); if(conn == NULL) { return; } espconn_delete(conn); if(conn->proto.tcp != NULL) { os_free(conn->proto.tcp); conn->proto.tcp = NULL; } if(conn != NULL) { os_free(conn); conn = NULL; } }
static void ICACHE_FLASH_ATTR free_conn(void) { PRINTF("free conn\n"); if(conn == NULL) { return; } espconn_delete(conn); if(conn->proto.tcp != NULL) { os_free(conn->proto.tcp); conn->proto.tcp = NULL; } if(conn != NULL) { os_free(conn); conn = NULL; } }
/** * @brief Setup commad of close ip link. * @param id: commad id number * @param pPara: AT input param * @retval None */ void ICACHE_FLASH_ATTR at_setupCmdCipclose(uint8_t id, char *pPara) { char temp[64]; uint8_t linkID; uint8_t i; // if(mdState == m_linked) // { // // } pPara++; if(at_ipMux == 0) { uart0_sendStr("MUX=0\r\n"); return; } linkID = atoi(pPara); if(linkID > at_linkMax) { at_backError; return; } if(linkID == at_linkMax) { if(serverEn) { /* restart */ uart0_sendStr("we must restart\r\n"); return; } for(linkID=0; linkID<at_linkMax; linkID++) { if(pLink[linkID].linkEn) { if(pLink[linkID].pCon->type == ESPCONN_TCP) { pLink[linkID].teToff = TRUE; specialAtState = FALSE; // pLink[linkID].linkEn = FALSE; espconn_disconnect(pLink[linkID].pCon); disAllFlag = TRUE; // os_free(pLink[linkID].pCon); // at_linkNum--; // if(at_linkNum == 0) // { // mdState = m_unlink; // uart0_sendStr("Unlink\r\n"); // } break; } else { pLink[linkID].linkEn = FALSE; espconn_delete(pLink[linkID].pCon); os_free(pLink[linkID].pCon->proto.udp);/// os_free(pLink[linkID].pCon); at_linkNum--; if(at_linkNum == 0) { mdState = m_unlink; at_backOk; uart0_sendStr("Unlink\r\n"); } } } } } else { if(pLink[linkID].linkEn == FALSE) { uart0_sendStr("link is not\r\n"); return; } if(pLink[linkID].teType == teServer) { if(pLink[linkID].pCon->type == ESPCONN_TCP) { pLink[linkID].teToff = TRUE; specialAtState = FALSE; espconn_disconnect(pLink[linkID].pCon); } else { pLink[linkID].linkEn = FALSE; espconn_delete(pLink[linkID].pCon); at_linkNum--; at_backOk; if(at_linkNum == 0) { mdState = m_unlink; uart0_sendStr("Unlink\r\n"); } } } else { if(pLink[linkID].pCon->type == ESPCONN_TCP) { pLink[linkID].teToff = TRUE; specialAtState = FALSE; espconn_disconnect(pLink[linkID].pCon); } else { pLink[linkID].linkEn = FALSE; espconn_delete(pLink[linkID].pCon); os_free(pLink[linkID].pCon->proto.udp); os_free(pLink[linkID].pCon); at_linkNum--; at_backOk; if(at_linkNum == 0) { mdState = m_unlink; uart0_sendStr("Unlink\r\n"); } } } } // if(pLink[linkID].pCon->type == ESPCONN_TCP) // { // specialAtState = FALSE; // espconn_disconnect(pLink[linkID].pCon); // } // else // { // pLink[linkID].linkEn = FALSE; // espconn_disconnect(pLink[linkID].pCon); // os_free(pLink[linkID].pCon->proto.udp); // os_free(pLink[linkID].pCon); // at_linkNum--; // at_backOk; // if(at_linkNum == 0) // { // mdState = m_unlink; // uart0_sendStr("Unlink\r\n"); // } // } // specialAtState = FALSE; }
/** * @brief Tcp client disconnect success callback function. * @param arg: contain the ip link information * @retval None */ static void ICACHE_FLASH_ATTR at_tcpclient_discon_cb(void *arg) { struct espconn *pespconn = (struct espconn *)arg; at_linkConType *linkTemp = (at_linkConType *)pespconn->reverse; uint8_t idTemp; if(pespconn == NULL) { return; } if(pespconn->proto.tcp != NULL) { os_free(pespconn->proto.tcp); } os_free(pespconn); linkTemp->linkEn = FALSE; os_printf("disconnect\r\n"); // os_printf("con EN? %d\r\n", pLink[0].linkEn); at_linkNum--; if(disAllFlag == FALSE) { at_backOk; } if(at_linkNum == 0) { mdState = m_unlink;////////////////////// if(disAllFlag) { at_backOk; } uart0_sendStr("Unlink\r\n"); ETS_UART_INTR_ENABLE(); /////transparent is over // specialAtState = TRUE; // at_state = at_statIdle; disAllFlag = FALSE; // specialAtState = TRUE; // at_state = at_statIdle; // return; } if(disAllFlag) { idTemp = linkTemp->linkId + 1; for(; idTemp<at_linkMax; idTemp++) { if(pLink[idTemp].linkEn) { if(pLink[idTemp].teType == teServer) { continue; } if(pLink[idTemp].pCon->type == ESPCONN_TCP) { specialAtState = FALSE; espconn_disconnect(pLink[idTemp].pCon); break; } else { pLink[idTemp].linkEn = FALSE; espconn_delete(pLink[idTemp].pCon); os_free(pLink[idTemp].pCon->proto.udp); os_free(pLink[idTemp].pCon); at_linkNum--; if(at_linkNum == 0) { mdState = m_unlink; at_backOk; uart0_sendStr("Unlink\r\n"); disAllFlag = FALSE; // specialAtState = TRUE; // at_state = at_statIdle; // return; } } } } } // IPMODE = FALSE; specialAtState = TRUE; at_state = at_statIdle; }
// Lua: server:listen( port, ip, function(con) ) // Lua: socket:connect( port, ip, function(con) ) static int net_start( lua_State* L, const char* mt ) { NODE_DBG("net_start is called.\n"); struct espconn *pesp_conn = NULL; lnet_userdata *nud; unsigned port; size_t il; bool isserver = false; ip_addr_t ipaddr; const char *domain; uint8_t stack = 1; 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_start.\n"); return 0; } nud = (lnet_userdata *)luaL_checkudata(L, stack, mt); luaL_argcheck(L, nud, stack, "Server/Socket expected"); stack++; if(nud==NULL){ NODE_DBG("userdata is nil.\n"); return 0; } pesp_conn = nud->pesp_conn; port = luaL_checkinteger( L, stack ); stack++; if( pesp_conn->type == ESPCONN_TCP ) { if(isserver) pesp_conn->proto.tcp->local_port = port; else{ pesp_conn->proto.tcp->remote_port = port; pesp_conn->proto.tcp->local_port = espconn_port(); } NODE_DBG("TCP port is set: %d.\n", port); } else if (pesp_conn->type == ESPCONN_UDP) { if(isserver) pesp_conn->proto.udp->local_port = port; else{ pesp_conn->proto.udp->remote_port = port; pesp_conn->proto.udp->local_port = espconn_port(); } NODE_DBG("UDP port is set: %d.\n", port); } if( lua_isstring(L,stack) ) // deal with the domain string { domain = luaL_checklstring( L, stack, &il ); stack++; if (domain == NULL) { if(isserver) domain = "0.0.0.0"; else domain = "127.0.0.1"; } ipaddr.addr = ipaddr_addr(domain); if( pesp_conn->type == ESPCONN_TCP ) { if(isserver) c_memcpy(pesp_conn->proto.tcp->local_ip, &ipaddr.addr, 4); else 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) { if(isserver) c_memcpy(pesp_conn->proto.udp->local_ip, &ipaddr.addr, 4); else 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"); } } // call back function when a connection is obtained, tcp only if ( pesp_conn->type == ESPCONN_TCP ) { if (lua_type(L, stack) == LUA_TFUNCTION || lua_type(L, stack) == LUA_TLIGHTFUNCTION){ lua_pushvalue(L, stack); // copy argument (func) to the top of stack if(isserver) // for tcp server connected callback { if(tcpserver_cb_connect_ref != LUA_NOREF) luaL_unref(L, LUA_REGISTRYINDEX, tcpserver_cb_connect_ref); tcpserver_cb_connect_ref = luaL_ref(L, LUA_REGISTRYINDEX); } else { if(nud->cb_connect_ref != LUA_NOREF) luaL_unref(L, LUA_REGISTRYINDEX, nud->cb_connect_ref); nud->cb_connect_ref = luaL_ref(L, LUA_REGISTRYINDEX); } } } if(!isserver || pesp_conn->type == ESPCONN_UDP){ // self_ref is only needed by socket userdata, or udp server lua_pushvalue(L, 1); // copy to the top of stack if(nud->self_ref != LUA_NOREF) luaL_unref(L, LUA_REGISTRYINDEX, nud->self_ref); nud->self_ref = luaL_ref(L, LUA_REGISTRYINDEX); } if( pesp_conn->type == ESPCONN_TCP ) { if(isserver){ // no secure server support for now espconn_regist_connectcb(pesp_conn, net_server_connected); // tcp server, SSL is not supported #ifdef CLIENT_SSL_ENABLE // if(nud->secure) // espconn_secure_accept(pesp_conn); // else #endif espconn_accept(pesp_conn); // if it's a server, no need to dns. espconn_regist_time(pesp_conn, tcp_server_timeover, 0); } else{ espconn_regist_connectcb(pesp_conn, net_socket_connected); espconn_regist_reconcb(pesp_conn, net_socket_reconnected); #ifdef CLIENT_SSL_ENABLE if(nud->secure){ if(pesp_conn->proto.tcp->remote_port || pesp_conn->proto.tcp->local_port) espconn_secure_disconnect(pesp_conn); // espconn_secure_connect(pesp_conn); } else #endif { if(pesp_conn->proto.tcp->remote_port || pesp_conn->proto.tcp->local_port) espconn_disconnect(pesp_conn); // espconn_connect(pesp_conn); } } } else if (pesp_conn->type == ESPCONN_UDP) { espconn_regist_recvcb(pesp_conn, net_socket_received); espconn_regist_sentcb(pesp_conn, net_socket_sent); if(pesp_conn->proto.tcp->remote_port || pesp_conn->proto.tcp->local_port) espconn_delete(pesp_conn); if(isserver) espconn_create(pesp_conn); // if it's a server, no need to dns. } if(!isserver){ if((ipaddr.addr == IPADDR_NONE) && (c_memcmp(domain,"255.255.255.255",16) != 0)) { host_ip.addr = 0; dns_reconn_count = 0; if(ESPCONN_OK == espconn_gethostbyname(pesp_conn, domain, &host_ip, socket_dns_found)){ socket_dns_found(domain, &host_ip, pesp_conn); // ip is returned in host_ip. } } else { socket_connect(pesp_conn); } } return 0; }
// Lua: server/socket:close() // server disconnect everything, unref everything // client disconnect and unref itself static int net_close( lua_State* L, const char* mt ) { NODE_DBG("net_close is called.\n"); bool isserver = false; int i = 0; lnet_userdata *nud = NULL, *skt = NULL; nud = (lnet_userdata *)luaL_checkudata(L, 1, mt); luaL_argcheck(L, nud, 1, "Server/Socket expected"); if(nud == NULL) return 0; if(nud->pesp_conn == NULL) return 0; 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_close.\n"); return 0; } if(isserver && nud->pesp_conn->type == ESPCONN_TCP && tcpserver_cb_connect_ref != LUA_NOREF){ luaL_unref(L, LUA_REGISTRYINDEX, tcpserver_cb_connect_ref); tcpserver_cb_connect_ref = LUA_NOREF; } int n = lua_gettop(L); skt = nud; do{ if(isserver && skt == NULL){ if(socket[i] != LUA_NOREF){ // there is client socket exists lua_rawgeti(L, LUA_REGISTRYINDEX, socket[i]); // get the referenced user_data to stack top #if 0 socket[i] = LUA_NOREF; socket_num--; #endif // do this in net_server_disconnected i++; if(lua_isuserdata(L,-1)){ skt = lua_touserdata(L,-1); } else { lua_pop(L, 1); continue; } }else{ // skip LUA_NOREF i++; continue; } } if(skt==NULL){ NODE_DBG("userdata is nil.\n"); continue; } if(skt->pesp_conn) // disconnect the connection { if(skt->pesp_conn->type == ESPCONN_TCP) { #ifdef CLIENT_SSL_ENABLE if(skt->secure){ if(skt->pesp_conn->proto.tcp->remote_port || skt->pesp_conn->proto.tcp->local_port) espconn_secure_disconnect(skt->pesp_conn); } else #endif { if(skt->pesp_conn->proto.tcp->remote_port || skt->pesp_conn->proto.tcp->local_port) espconn_disconnect(skt->pesp_conn); } }else if(skt->pesp_conn->type == ESPCONN_UDP) { if(skt->pesp_conn->proto.tcp->remote_port || skt->pesp_conn->proto.tcp->local_port) espconn_delete(skt->pesp_conn); // a udp server/socket unref it self here. not in disconnect. if(LUA_NOREF!=skt->self_ref){ // for a udp self_ref is NOREF luaL_unref(L, LUA_REGISTRYINDEX, skt->self_ref); skt->self_ref = LUA_NOREF; // for a socket, now only var in lua is ref to the userdata } } } #if 0 // unref the self_ref if(LUA_NOREF!=skt->self_ref){ // for a server self_ref is NOREF luaL_unref(L, LUA_REGISTRYINDEX, skt->self_ref); skt->self_ref = LUA_NOREF; // for a socket, now only var in lua is ref to the userdata } #endif lua_settop(L, n); // reset the stack top skt = NULL; } while( isserver && i<MAX_SOCKET); #if 0 // unref the self_ref, for both socket and server if(LUA_NOREF!=nud->self_ref){ // for a server self_ref is NOREF luaL_unref(L, LUA_REGISTRYINDEX, nud->self_ref); nud->self_ref = LUA_NOREF; // now only var in lua is ref to the userdata } #endif return 0; }