/** * Error handler callback. * Although this is called `reconnect` by Espressif, this is really a connection reset callback. */ static void esp8266_callback_reconnectCB( void *arg, //!< A pointer to a `struct espconn`. sint8 err //!< The error code. ) { struct espconn *pEspconn = (struct espconn *)arg; struct socketData *pSocketData = (struct socketData *)pEspconn->reverse; if (pSocketData == NULL) return; // we already closed this. //if (pEspconn != pSocketData->pEspconn) DBG("%s: pEspconn changed in reconnectCB ***\n", DBG_LIB); DBG("%s: socket %d connection reset: Err %d - %s\n", DBG_LIB, pSocketData->socketId, err, esp8266_errorToString(err)); // Do the same as for a disconnect esp8266_callback_disconnectCB(arg); // Set the socket state as in error (unless it got freed by esp8266_callback_disconnectCB) if (pSocketData->state != SOCKET_STATE_UNUSED) setSocketInError(pSocketData, err); //DBG("%s: ret from reconnectCB\n", DBG_LIB); }
/** * ESP8266 callback function that is invoked when new data has arrived over * the TCP/IP connection. */ static void esp8266_callback_recvCB( void *arg, //!< A pointer to a `struct espconn`. char *pData, //!< A pointer to data received over the socket. unsigned short len //!< The length of the data. ) { struct espconn *pEspconn = (struct espconn *)arg; struct socketData *pSocketData = (struct socketData *)pEspconn->reverse; if (pSocketData == NULL) return; // we closed this socket //if (pEspconn != pSocketData->pEspconn) DBG("%s: pEspconn changed in recvCB ***\n", DBG_LIB); assert(pSocketData->state != SOCKET_STATE_UNUSED); //DBG("%s: socket %d recv %d\n", DBG_LIB, pSocketData->socketId, len); //DBG("%s: recv data: %p\n", DBG_LIB, pData); // if this is a dead connection then just ignore the callback if (pSocketData->state == SOCKET_STATE_ABORTING || pSocketData->state == SOCKET_STATE_TO_ABORT || pSocketData->state == SOCKET_STATE_CLOSED || pSocketData->state == SOCKET_STATE_DISCONNECTING) { return; } // Allocate a buffer and add to the receive queue PktBuf *buf = PktBuf_New(len); if (!buf) { // handle out of memory condition DBG("%s: Out of memory allocating %d for recv\n", DBG_LIB, len); // at this point we're gonna deallocate all receive buffers as a panic measure while (pSocketData->rxBufQ != NULL) pSocketData->rxBufQ = PktBuf_ShiftFree(pSocketData->rxBufQ); // save the error setSocketInError(pSocketData, ESPCONN_MEM); // now reset the connection //espconn_abort(pEspconn); // can't do this: espconn crashes! pSocketData->state = SOCKET_STATE_TO_ABORT; // some function called from socket lib will abort //DBG("%s: ret from recvCB\n", DBG_LIB); return; } // if this is the second buffer then stop the flood! if (pSocketData->rxBufQ != NULL) espconn_recv_hold(pEspconn); // got buffer, fill it os_memcpy(buf->data, pData, len); buf->filled = len; pSocketData->rxBufQ = PktBuf_Push(pSocketData->rxBufQ, buf); }
/** * Create a new socket. * if `ipAddress == 0`, creates a server otherwise creates a client (and automatically connects). Returns >=0 on success. */ int net_ESP8266_BOARD_createSocket( JsNetwork *net, //!< The Network we are going to use to create the socket. uint32_t ipAddress, //!< The address of the partner of the socket or 0 if we are to be a server. unsigned short port //!< The port number that the partner is listening upon. ) { os_printf("> net_ESP8266_BOARD_createSocket: host: %d.%d.%d.%d, port:%d \n", ((char *)(&ipAddress))[0], ((char *)(&ipAddress))[1], ((char *)(&ipAddress))[2], ((char *)(&ipAddress))[3], port); bool isServer = (ipAddress == 0); struct socketData *pSocketData = allocateNewSocket(); if (pSocketData == NULL) { // No free socket os_printf("< net_ESP8266_BOARD_createSocket: No free sockets\n"); return -1; } int newSocket = pSocketData->socketId; pSocketData->pEspconn = (struct espconn *)os_malloc(sizeof(struct espconn)); assert(pSocketData->pEspconn); struct espconn *pEspconn = pSocketData->pEspconn; pEspconn->type = ESPCONN_TCP; pEspconn->state = ESPCONN_NONE; pEspconn->proto.tcp = (esp_tcp *)os_malloc(sizeof(esp_tcp)); pEspconn->reverse = pSocketData; assert(pEspconn->proto.tcp != NULL); os_memset(pEspconn->proto.tcp, 0, sizeof(esp_tcp)); // NOTE: We must not call these functions until AFTER we have allocated storage // for the 'esp_tcp' structure. espconn_regist_disconcb(pEspconn, esp8266_callback_disconnectCB); espconn_regist_reconcb(pEspconn, esp8266_callback_reconnectCB); espconn_regist_sentcb(pEspconn, esp8266_callback_sentCB); espconn_regist_recvcb(pEspconn, esp8266_callback_recvCB); espconn_regist_write_finish(pEspconn, esp8266_callback_writeFinishedCB); struct ip_info ipconfig; wifi_get_ip_info(STATION_IF, &ipconfig); // Get the local IP address os_memcpy(pEspconn->proto.tcp->local_ip, &ipconfig.ip, 4); // If we are not a server ... if (isServer == false) { pSocketData->state = SOCKET_STATE_CONNECTING; pSocketData->creationType = SOCKET_CREATED_OUTBOUND; pEspconn->proto.tcp->remote_port = port; pEspconn->proto.tcp->local_port = espconn_port(); *(uint32 *)(pEspconn->proto.tcp->remote_ip) = ipAddress; // Ensure that we have flagged this socket as NOT connected pSocketData->isConnected = false; espconn_regist_connectcb(pEspconn, esp8266_callback_connectCB_outbound); // Make a call to espconn_connect. int rc = espconn_connect(pEspconn); if (rc != 0) { os_printf("Err: net_ESP8266_BOARD_createSocket -> espconn_connect returned: %d. Using local port: %d\n", rc, pEspconn->proto.tcp->local_port); setSocketInError(newSocket, "espconn_connect", rc); } } // If the ipAddress IS 0 ... then we are a server. else { // We are going to set ourselves up as a server pSocketData->state = SOCKET_STATE_IDLE; pSocketData->creationType = SOCKET_CREATED_SERVER; pEspconn->proto.tcp->local_port = port; espconn_regist_connectcb(pEspconn, esp8266_callback_connectCB_inbound); // Make a call to espconn_accept int rc = espconn_accept(pEspconn); if (rc != 0) { os_printf("Err: net_ESP8266_BOARD_createSocket -> espconn_accept returned: %d. Using local port: %d\n", rc, pEspconn->proto.tcp->local_port); setSocketInError(newSocket, "espconn_accept", rc); } } dumpEspConn(pEspconn); os_printf("< net_ESP8266_BOARD_createSocket, socket=%d\n", newSocket); return newSocket; }