Chat freely about anything...

User avatar
By htwtsang
#70951 I currently am having a problem with using ESP-WROOM-02 and using esphttpd library. I am trying to get the espressif IOT demo to work on the device but I get an error when I connect to the device via browser. It works on my PC then it gets stuck in a while(1) loop in the httpd.c file (void httpserver_task(void *pvParameters)) , if I refresh the page. I have yet been able to get the device to work on any other mobile or PC.

I have discovered that the following line is returning -1 which is an error with the semaphore, ret = select(maxfdp+1, &readset, &writeset, NULL, NULL);. This could be an error from the readset or writeset from the “for” loop above it.

Code: Select all#define RECV_BUF_SIZE 2048
LOCAL void httpserver_task(void *pvParameters)
{
   printf("httpserver_task start!!!\n");
    int32 listenfd;
    int32 remotefd;
    int32 len;
    int32 ret;
    u8    index;
   
    u32 maxfdp = 0;
    fd_set readset,writeset;
    //struct timeval timeout;
    struct sockaddr_in server_addr;
    struct sockaddr_in remote_addr;

//    portBASE_TYPE xStatus;
//    bool ValueFromReceive = false;

    char *precvbuf = (char*)malloc(RECV_BUF_SIZE);
    if(NULL == precvbuf){
        printf("httpserver_task memory exhausted!!!\n");
    }
   
   
    /* Construct local address structure */
    memset(&server_addr, 0, sizeof(server_addr)); /* Zero out structure */
    server_addr.sin_family = AF_INET;            /* Internet address family */
    server_addr.sin_addr.s_addr = INADDR_ANY;   /* Any incoming interface */
    server_addr.sin_len = sizeof(server_addr); 
    server_addr.sin_port = htons(httpd_server_port); /* Local port */

    /* Create socket for incoming connections */
    do{
        listenfd = socket(AF_INET, SOCK_STREAM, 0);
        if (listenfd == -1) {
            printf("httpserver_task failed to create sock!\n");
            vTaskDelay(1000/portTICK_RATE_MS);
        }
    }while(listenfd == -1);

    /* Bind to the local port */
    do{
        ret = bind(listenfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
        if (ret != 0) {
            printf("httpserver_task failed to bind!\n");
            vTaskDelay(1000/portTICK_RATE_MS);
        }
    }while(ret != 0);

    do{
        /* Listen to the local connection */
        ret = listen(listenfd, MAX_CONN);
        if (ret != 0) {
            printf("httpserver_task failed to listen!\n");
            vTaskDelay(1000/portTICK_RATE_MS);
        }
       
    }while(ret != 0);
   
    while(1){
        /*clear fdset, and set the selct function wait time*/
        maxfdp = 0;
        FD_ZERO(&readset);
        FD_ZERO(&writeset);
        //timeout.tv_sec = 2;
        //timeout.tv_usec = 0;

        for(index=0; index < MAX_CONN; index++){
            //find all valid handle
           printf("1index = %i\n",index);
            if (connData[index].conn!=NULL) {
                if(connData[index].conn->sockfd >= 0){
                   printf("2index = %i\n",index);
                   FD_SET(connData[index].conn->sockfd, &readset);
                   if(connData[index].cgi != NULL || connData[index].destruct_flg==TRUE) {
                        FD_SET(connData[index].conn->sockfd, &writeset);
                        printf("index %d, sockfd %d to wselect\n",index, connData[index].conn->sockfd);
                    }else{
                        printf("index %d, sockfd %d, dummy?\n",index, connData[index].conn->sockfd);
                        printf("destruct_flg = %c \n",connData[index].destruct_flg);
                        printf("cgi add = %p \n",connData[index].cgi);
                    }
                    maxfdp = max(connData[index].conn->sockfd, maxfdp);
        }}}
        /*add listenfd to readset*/
        FD_SET(listenfd, &readset);
        maxfdp = max(listenfd, maxfdp);

        //polling all exist client handle,wait until readable/writable
        ret = select(maxfdp+1, &readset, &writeset, NULL, NULL);//&timeout
        printf("listenfd = %d\n",listenfd);
        printf("maxfdp = %d\n",maxfdp);
        printf("ret = %d\n",ret);
        if(ret > 0){

            if (FD_ISSET(listenfd, &readset)){

                len = sizeof(struct sockaddr_in);
                remotefd = accept(listenfd, (struct sockaddr *)&remote_addr, (socklen_t *)&len);
                if(remotefd != -1) {
                    index=0;
                    //find the fisrt usable connection to save the handle.
                    for(index=0; index < MAX_CONN; index++){
                        if(connData[index].conn == NULL)break;
                    }
           
                    if(index < MAX_CONN){

                        int keepAlive = 1; //enable keepalive
                        int keepIdle = 60; //60s
                        int keepInterval = 5; //5s
                        int keepCount = 3; //retry times
                       
                        setsockopt(remotefd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepAlive, sizeof(keepAlive));//
                        setsockopt(remotefd, IPPROTO_TCP, TCP_KEEPIDLE, (void*)&keepIdle, sizeof(keepIdle));
                        setsockopt(remotefd, IPPROTO_TCP, TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval));
                        setsockopt(remotefd, IPPROTO_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount));
                       
                        connData[index].priv=&connPrivData[index];
                        connData[index].priv->headPos=0;
                        connData[index].post=&connPostData[index];
                        connData[index].post->buff=NULL;
                        connData[index].post->buffLen=0;
                        connData[index].post->received=0;
                        connData[index].post->len=-1;
                        connData[index].hostName=NULL;
                        connData[index].conn =&sockData[index];
                        connData[index].conn->sockfd = remotefd;
                        connData[index].conn->timeout = 0;
                        connData[index].destruct_flg=FALSE;
               
                        struct sockaddr name;
                        int len = sizeof(name);
                        getpeername(connData->conn->sockfd, &name, (socklen_t *)&len);
                        struct sockaddr_in *piname=(struct sockaddr_in *)&name;
                        connData[index].remote_port = piname->sin_port;
                        connData[index].remote_ip=piname->sin_addr.s_addr;
               
                        os_timer_disarm(&connData[index].conn->stop_watch);
                        os_timer_setfn(&connData[index].conn->stop_watch, (os_timer_func_t *)httpserver_conn_watcher, connData[index].conn);
                        os_timer_arm(&connData[index].conn->stop_watch, STOP_TIMER, 0);
                        printf("httpserver acpt index:%d sockfd %d!\n",index,remotefd);
                    }else{
                        close(remotefd);
                        printf("httpserver overflow close %d!\n",remotefd);
                    }
       
                }else{
                    printf("http client error: %d, WARNING!\n",remotefd);
                }
            }
           
            for(index=0; index < MAX_CONN; index++){
               
                /* IF this handle there is data/event aviliable, recive it*/
                if (connData[index].conn == NULL) continue;
                if (FD_ISSET(connData[index].conn->sockfd, &readset)){

                    /*stop the sock handle watchout timer */
                    os_timer_disarm((os_timer_t *)&connData[index].conn->stop_watch);
                    memset(precvbuf, 0, RECV_BUF_SIZE);

                    ret=recv(connData[index].conn->sockfd,precvbuf,RECV_BUF_SIZE,0);
                    if(ret > 0){
/*
                        struct sockaddr name;
                        struct sockaddr_in *piname;
                        int len = sizeof(name);
                        getpeername(pconnections->single_conn[index]->sock_fd, &name, (socklen_t *)&len);
                        piname  = (struct sockaddr_in *)&name;
*/
                        printf("readable recv sockfd %d len=%d \n",connData[index].conn->sockfd,ret);
                        httpdRecv(connData[index].conn,precvbuf,ret);

                        /*restart the sock handle watchout timer */
                        os_timer_setfn((os_timer_t *)&connData[index].conn->stop_watch, (os_timer_func_t *)httpserver_conn_watcher, connData[index].conn);
                        os_timer_arm((os_timer_t *)&connData[index].conn->stop_watch, STOP_TIMER, 0);
                    }else{
                        //recv error,connection close
                        printf("readable recv sockfd %d ret=%d, close\n",connData[index].conn->sockfd,ret);
                        close(connData[index].conn->sockfd);
                        connData[index].conn->sockfd = -1;
                        connData[index].conn = NULL;// flag for cgi flush data
                        if (connData[index].cgi!=NULL) connData[index].cgi(&connData[index]); //flush cgi data
                        httpdRetireConn(&connData[index]);
                    }
                   
                }
               
                if (connData[index].conn == NULL) continue;
                if(FD_ISSET(connData[index].conn->sockfd, &writeset)){
                    /*stop the sock handle watchout timer */
                    os_timer_disarm((os_timer_t *)&connData[index].conn->stop_watch);
                    memset(precvbuf, 0, RECV_BUF_SIZE);

                    connData[index].priv->sendBuff=precvbuf;
                    connData[index].priv->sendBuffLen=0;

                    if (connData[index].destruct_flg==TRUE) { //Marked for destruction
                        printf("httpserver destruction close sockfd %d\n", connData[index].conn->sockfd);
                        close(connData[index].conn->sockfd);
                        connData[index].conn->sockfd = -1;
                        httpdRetireConn(&connData[index]);
                       
                    } else if(connData[index].cgi != NULL){
                        ret=connData[index].cgi(&connData[index]); //Execute cgi fn.
                        if (ret==HTTPD_CGI_DONE) {
                            connData[index].cgi=NULL; //mark for destruction.
                            connData[index].destruct_flg=TRUE;
                        }
                        if (ret==HTTPD_CGI_NOTFOUND || ret==HTTPD_CGI_AUTHENTICATED) {
                            printf("ERROR! CGI fn returns code %d after sending data! Bad CGI!\n", ret);
                            connData[index].cgi=NULL; //mark for destruction.
                            connData[index].destruct_flg=TRUE;
                        }
                        xmitSendBuff(&connData[index]);
                       
                        /*restart the sock handle watchout timer */
                        os_timer_setfn((os_timer_t *)&connData[index].conn->stop_watch, (os_timer_func_t *)httpserver_conn_watcher, connData[index].conn);
                        os_timer_arm((os_timer_t *)&connData[index].conn->stop_watch, STOP_TIMER, 0);
                    }
                }
                /* IF this handle there is no data/event aviliable, check the status*/
                if(connData[index].conn == NULL) continue;
                if(connData[index].conn->timeout == 1){
                    printf("httpserver close sockfd %d 4timeout!\n",connData[index].conn->sockfd);
                    close(connData[index].conn->sockfd);
                    connData[index].conn->sockfd = -1;
                    connData[index].conn = NULL; //mark for destruction.
                    if (connData[index].cgi!=NULL) {
                        connData[index].cgi(&connData[index]); //flush cgi data
                        printf("cgi!=null,should never happen\n");
                    }
                    httpdRetireConn(&connData[index]);
                }
            }
        }

#if 1
        /*for develop test only*/
        printf("httpserver_task %d words, heap %d bytes\n",(int)uxTaskGetStackHighWaterMark(NULL), system_get_free_heap_size());
#endif

    }

    //this stuff is not included in the bin (maybe from the while (1) loop?)-hugo
    /*release data connection*/
    for(index=0; index < MAX_CONN; index++){
        //find all valid handle
        if(connData[index].conn == NULL) continue;
        if(connData[index].conn->sockfd >= 0){
            os_timer_disarm((os_timer_t *)&connData[index].conn->stop_watch);
            close(connData[index].conn->sockfd);
            connData[index].conn->sockfd = -1;
            connData[index].conn = NULL;
            if(connData[index].cgi!=NULL) connData[index].cgi(&connData[index]); //flush cgi data
            httpdRetireConn(&connData[index]);
        }
    }
    /*release listen socket*/
    close(listenfd);

    if(NULL != precvbuf){
        free(precvbuf);
    }
    vTaskDelete(NULL);
}


Can someone give me a suggestion on how to solve this?