/**
 * 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);
}
Beispiel #3
0
/**
 * 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;
}