void prepareClient(ClientsContainer * container, sf::TcpSocket ** acceptSocket) { //create the new Client Client * newClient = new Client; if(newClient == NULL) { printf("Failed to allocate Client\n"); exit(1); } newClient->socket = *acceptSocket; container->containerMutex->lock(); container->selector->add(*newClient->socket); int ClientId = container->list->add(newClient); container->containerMutex->unlock(); //create and launch a protocol connect thread sf::Thread * newConnectThread = new sf::Thread(&connectProtocol,ConnectDataSet(container,ClientId)); if(newConnectThread == NULL) { printf("Failed to allocate thread\n"); exit(1); } newConnectThread->launch(); allocateNewSocket(acceptSocket); //reset for the next Client }
/** * Callback function registered to the ESP8266 environment that is * invoked when a new inbound connection has been formed. */ static void esp8266_callback_connectCB_inbound( void *arg //!< ) { struct espconn *pEspconn = (struct espconn *)arg; assert(pEspconn != NULL); struct socketData *pClientSocketData = allocateNewSocket(); if (pClientSocketData == NULL) { DBG("%s: out of sockets, dropping inbound connection\n", DBG_LIB); espconn_disconnect(pEspconn); return; } DBG("%s: accepted socket %d inbound to port %d from %d.%d.%d.%d:%d\n", DBG_LIB, pClientSocketData->socketId, pEspconn->proto.tcp->local_port, IP2STR(pEspconn->proto.tcp->remote_ip), pEspconn->proto.tcp->remote_port); //dumpEspConn(pEspconn); // register callbacks on the new connection 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); pClientSocketData->pEspconn = pEspconn; pClientSocketData->pEspconn->reverse = pClientSocketData; pClientSocketData->creationType = SOCKET_CREATED_INBOUND; pClientSocketData->state = SOCKET_STATE_UNACCEPTED; }
void answerToClient(AnswerDataSet data) //AnswerDataSet = List<Client*> * list, sf::Mutex * listMutex, int port { sf::TcpListener listener; setupListener(&listener, data.port); sf::TcpSocket * acceptSocket; // always keep one allocated allocateNewSocket(&acceptSocket); while(1) { data.container->containerMutex->lock(); bool isFull = (data.container->list->getSize() == data.maxClient); data.container->containerMutex->unlock(); if(isFull) { while(listenerAccept(&listener,acceptSocket)) { logger.printDebug("Refusing"); sendFullMessage(acceptSocket); acceptSocket->disconnect(); } } else { while(listenerAccept(&listener,acceptSocket)) { prepareClient(data.container,&acceptSocket); data.container->containerMutex->lock(); isFull = (data.container->list->getSize() == data.maxClient); data.container->containerMutex->unlock(); if(isFull) // stops accepting if full { break; } } } if(checkStopThreads()) { return; } sf::sleep(sf::milliseconds(10)); } }
/** * Callback function registered to the ESP8266 environment that is * invoked when a new inbound connection has been formed. * A new connection * can occur when the ESP8266 makes a call out to a partner (in that * case the ESP8266 is acting as a client) or a new connection can * occur when a partner calls into a listening ESP8266. In that case * the ESP8266 is acting as a server. */ static void esp8266_callback_connectCB_inbound( void *arg //!< ) { os_printf(">> connectCB_inbound\n"); struct espconn *pEspconn = (struct espconn *)arg; assert(pEspconn != NULL); 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); dumpEspConn(pEspconn); int inboundSocket = getServerSocketByLocalPort(pEspconn->proto.tcp->local_port); assert(inboundSocket != -1); struct socketData *pSocketData = getSocketData(inboundSocket); assert(pSocketData != NULL); esp8266_dumpSocket(pSocketData->socketId); os_printf("** new client has connected to us **\n"); if ((pSocketData->acceptedSocketsHead + 1) % MAX_ACCEPTED_SOCKETS == pSocketData->acceptedSocketsTail) { os_printf("WARNING!! - Discarding inbound client because we have too many accepted clients.\n"); os_printf("<< connectCB_inbound\n"); return; } struct socketData *pClientSocketData = allocateNewSocket(); if (pClientSocketData == NULL) { os_printf("!!! Ran out of sockets !!!\n"); return; } assert(pClientSocketData != NULL); pClientSocketData->pEspconn = pEspconn; pClientSocketData->pEspconn->reverse = pClientSocketData; pClientSocketData->creationType = SOCKET_CREATED_INBOUND; pClientSocketData->isConnected = true; pClientSocketData->state = SOCKET_STATE_IDLE; pSocketData->acceptedSockets[pSocketData->acceptedSocketsHead] = pClientSocketData->socketId; pSocketData->acceptedSocketsHead = (pSocketData->acceptedSocketsHead + 1) % MAX_ACCEPTED_SOCKETS; os_printf("<< connectCB_inbound\n"); }
/** * 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. ) { // allocate a socket data structure struct socketData *pSocketData = allocateNewSocket(); if (pSocketData == NULL) { // No free socket DBG("%s: No free sockets for outbound connection\n", DBG_LIB); return SOCKET_ERR_MAX_SOCK; } // allocate espconn data structure and initialize it struct espconn *pEspconn = os_zalloc(sizeof(struct espconn)); esp_tcp *tcp = os_zalloc(sizeof(esp_tcp)); if (pEspconn == NULL || tcp == NULL) { DBG("%s: Out of memory for outbound connection\n", DBG_LIB); if (pEspconn != NULL) os_free(pEspconn); if (tcp != NULL) os_free(tcp); releaseSocket(pSocketData); return SOCKET_ERR_MEM; } pSocketData->pEspconn = pEspconn; pEspconn->type = ESPCONN_TCP; pEspconn->state = ESPCONN_NONE; pEspconn->proto.tcp = tcp; tcp->remote_port = port; tcp->local_port = espconn_port(); // using 0 doesn't work pEspconn->reverse = pSocketData; espconn_set_opt(pEspconn, ESPCONN_NODELAY); // disable nagle, don't need the extra delay if (ipAddress == (uint32_t)-1) { // We need DNS resolution, kick it off int rc = espconn_gethostbyname(pEspconn, savedHostname, (void*)&pEspconn->proto.tcp->remote_ip, dnsFoundCallback); if (rc < 0) { } DBG("%s: resolving %s\n", DBG_LIB, savedHostname); pSocketData->state = SOCKET_STATE_HOST_RESOLVING; return pSocketData->socketId; } else { // No DNS resolution needed, go right ahead *(uint32_t *)&pEspconn->proto.tcp->remote_ip = ipAddress; return connectSocket(pSocketData); } }
/** * 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; }