/** * Send data to the partner. * The return is the number of bytes actually transmitted which may also be * 0 to indicate no bytes sent or -1 to indicate an error. For the ESP8266 implementation we * will return 0 if the socket is not connected or we are in the `SOCKET_STATE_TRANSMITTING` * state. */ int net_ESP8266_BOARD_send( JsNetwork *net, //!< The Network we are going to use to create the socket. int sckt, //!< The socket over which we will send data. const void *buf, //!< The buffer containing the data to be sent. size_t len //!< The length of data in the buffer to send. ) { //DBG("%s:send\n", DBG_LIB); struct socketData *pSocketData = getSocketData(sckt); assert(pSocketData->state != SOCKET_STATE_UNUSED); // If the socket is in error or it is closing return -1 switch (pSocketData->state) { case SOCKET_STATE_CLOSED: case SOCKET_STATE_DISCONNECTING: return pSocketData->errorCode != 0 ? pSocketData->errorCode : SOCKET_ERR_CLOSED; case SOCKET_STATE_ABORTING: return pSocketData->errorCode; case SOCKET_STATE_TO_ABORT: espconn_abort(pSocketData->pEspconn); return pSocketData->errorCode; default: break; } // Unless we are in the idle state, we can't send more shtuff if (pSocketData->state != SOCKET_STATE_IDLE) { return 0; } // Log the content of the data we are sending. //esp8266_board_writeString(buf, len); //os_printf("\n"); // Copy the data to be sent into a transmit buffer we hand off to espconn assert(pSocketData->currentTx == NULL); pSocketData->currentTx = (uint8_t *)os_malloc(len); if (pSocketData->currentTx == NULL) { DBG("%s: Out of memory sending %d on socket %d\n", DBG_LIB, len, sckt); setSocketInError(pSocketData, ESPCONN_MEM); espconn_abort(pSocketData->pEspconn); pSocketData->state = SOCKET_STATE_ABORTING; return pSocketData->errorCode; } memcpy(pSocketData->currentTx, buf, len); // Send the data over the ESP8266 SDK. int rc = espconn_send(pSocketData->pEspconn, pSocketData->currentTx, len); if (rc < 0) { setSocketInError(pSocketData, rc); os_free(pSocketData->currentTx); pSocketData->currentTx = NULL; espconn_abort(pSocketData->pEspconn); pSocketData->state = SOCKET_STATE_ABORTING; return rc; } pSocketData->state = SOCKET_STATE_TRANSMITTING; //DBG("%s: socket %d JS send %d\n", DBG_LIB, sckt, len); return len; }
/** * 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; } }
/** * Receive data from the network device. * Returns the number of bytes received which may be 0 and <0 if there was an error. */ int net_ESP8266_BOARD_recv( JsNetwork *net, //!< The Network we are going to use to create the socket. int sckt, //!< The socket from which we are to receive data. void *buf, //!< The storage buffer into which we will receive data. size_t len //!< The length of the buffer. ) { //DBG("%s:recv\n", DBG_LIB); struct socketData *pSocketData = getSocketData(sckt); assert(pSocketData); assert(pSocketData->state != SOCKET_STATE_UNUSED); // handle socket that needs aborting if (pSocketData->state == SOCKET_STATE_TO_ABORT) { espconn_abort(pSocketData->pEspconn); return pSocketData->errorCode; } // If there is no data in the receive buffer, then all we need do is return // 0 bytes as the length of data moved or -1 if the socket is actually closed. if (pSocketData->rxBufQ == NULL) { switch (pSocketData->state) { case SOCKET_STATE_CLOSED: return pSocketData->errorCode != 0 ? pSocketData->errorCode : SOCKET_ERR_CLOSED; case SOCKET_STATE_DISCONNECTING: case SOCKET_STATE_ABORTING: return pSocketData->errorCode; case SOCKET_STATE_HOST_RESOLVING: case SOCKET_STATE_CONNECTING: return SOCKET_ERR_NO_CONN; default: return 0; // we just have no data } } PktBuf *rxBuf = pSocketData->rxBufQ; // If the receive buffer is able to completely fit in the buffer // passed into us then we can copy all the data and the receive buffer will be clear. if (rxBuf->filled <= len) { os_memcpy(buf, rxBuf->data, rxBuf->filled); int retLen = rxBuf->filled; pSocketData->rxBufQ = PktBuf_ShiftFree(rxBuf); // if we now have exactly one buffer enqueued we need to re-enable the flood if (pSocketData->rxBufQ != NULL && pSocketData->rxBufQ->next == NULL) espconn_recv_unhold(pSocketData->pEspconn); //DBG("%s: socket %d JS recv %d\n", DBG_LIB, sckt, retLen); return retLen; } // If we are here, then we have more data in the receive buffer than is available // to be returned in this request for data. So we have to copy the amount of data // that is allowed to be returned and then strip that from the beginning of the // receive buffer. // First we copy the data we are going to return. os_memcpy(buf, rxBuf->data, len); // Next we shift up the remaining data uint16_t newLen = rxBuf->filled - len; os_memmove(rxBuf->data, rxBuf->data + len, newLen); rxBuf->filled = newLen; //DBG("%s: socket %d JS recv %d\n", DBG_LIB, sckt, len); return len; }