/* ESP8266 web server - platform-dependent routines, FreeRTOS version Thanks to my collague at Espressif for writing the foundations of this code. */ #ifdef FREERTOS #include #include "httpd.h" #include "platform.h" #include "httpd-platform.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" #include "lwip/lwip/sockets.h" static int httpPort; static int httpMaxConnCt; struct RtosConnType{ int fd; int needWriteDoneNotif; int needsClose; int port; char ip[4]; }; static RtosConnType rconn[HTTPD_MAX_CONNECTIONS]; int ICACHE_FLASH_ATTR httpdPlatSendData(ConnTypePtr conn, char *buff, int len) { conn->needWriteDoneNotif=1; return (write(conn->fd, buff, len)>=0); } void ICACHE_FLASH_ATTR httpdPlatDisconnect(ConnTypePtr conn) { conn->needsClose=1; conn->needWriteDoneNotif=1; //because the real close is done in the writable select code } void httpdPlatDisableTimeout(ConnTypePtr conn) { //Unimplemented for FreeRTOS } #define RECV_BUF_SIZE 2048 static void platHttpServerTask(void *pvParameters) { int32 listenfd; int32 remotefd; int32 len; int32 ret; int x; int maxfdp = 0; char *precvbuf; fd_set readset,writeset; struct sockaddr name; //struct timeval timeout; struct sockaddr_in server_addr; struct sockaddr_in remote_addr; for (x=0; xmaxfdp) maxfdp=rconn[x].fd; } else { socketsFull=0; } } if (!socketsFull) { FD_SET(listenfd, &readset); if (listenfd>maxfdp) maxfdp=listenfd; } //polling all exist client handle,wait until readable/writable ret = select(maxfdp+1, &readset, &writeset, NULL, NULL);//&timeout if(ret > 0){ //See if we need to accept a new connection if (FD_ISSET(listenfd, &readset)) { len=sizeof(struct sockaddr_in); remotefd = accept(listenfd, (struct sockaddr *)&remote_addr, (socklen_t *)&len); if (remotefd<0) { httpd_printf("platHttpServerTask: Huh? Accept failed.\n"); continue; } for(x=0; xsin_port; memcpy(&rconn[x].ip, &piname->sin_addr.s_addr, sizeof(rconn[x].ip)); httpdConnectCb(&rconn[x], rconn[x].ip, rconn[x].port); //os_timer_disarm(&connData[x].conn->stop_watch); //os_timer_setfn(&connData[x].conn->stop_watch, (os_timer_func_t *)httpserver_conn_watcher, connData[x].conn); //os_timer_arm(&connData[x].conn->stop_watch, STOP_TIMER, 0); // httpd_printf("httpserver acpt index %d sockfd %d!\n", x, remotefd); } //See if anything happened on the existing connections. for(x=0; x < HTTPD_MAX_CONNECTIONS; x++){ //Skip empty slots if (rconn[x].fd==-1) continue; //Check for write availability first: the read routines may write needWriteDoneNotif while //the select didn't check for that. if (rconn[x].needWriteDoneNotif && FD_ISSET(rconn[x].fd, &writeset)) { rconn[x].needWriteDoneNotif=0; //Do this first, httpdSentCb may write something making this 1 again. if (rconn[x].needsClose) { //Do callback and close fd. httpdDisconCb(&rconn[x], rconn[x].ip, rconn[x].port); close(rconn[x].fd); rconn[x].fd=-1; } else { httpdSentCb(&rconn[x], rconn[x].ip, rconn[x].port); } } if (FD_ISSET(rconn[x].fd, &readset)) { precvbuf=(char*)malloc(RECV_BUF_SIZE); if (precvbuf==NULL) httpd_printf("platHttpServerTask: memory exhausted!\n"); ret=recv(rconn[x].fd, precvbuf, RECV_BUF_SIZE,0); if (ret > 0) { //Data received. Pass to httpd. httpdRecvCb(&rconn[x], rconn[x].ip, rconn[x].port, precvbuf, ret); } else { //recv error,connection close httpdDisconCb(&rconn[x], rconn[x].ip, rconn[x].port); close(rconn[x].fd); rconn[x].fd=-1; } if (precvbuf) free(precvbuf); } } } } #if 0 //Deinit code, not used here. /*release data connection*/ for(x=0; x < HTTPD_MAX_CONNECTIONS; x++){ //find all valid handle if(connData[x].conn == NULL) continue; if(connData[x].conn->sockfd >= 0){ os_timer_disarm((os_timer_t *)&connData[x].conn->stop_watch); close(connData[x].conn->sockfd); connData[x].conn->sockfd = -1; connData[x].conn = NULL; if(connData[x].cgi!=NULL) connData[x].cgi(&connData[x]); //flush cgi data httpdRetireConn(&connData[x]); } } /*release listen socket*/ close(listenfd); vTaskDelete(NULL); #endif } //Initialize listening socket, do general initialization void ICACHE_FLASH_ATTR httpdPlatInit(int port, int maxConnCt) { httpPort=port; httpMaxConnCt=maxConnCt; xTaskCreate(platHttpServerTask, (const signed char *)"esphttpd", HTTPD_STACKSIZE, NULL, 4, NULL); } #endif