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.
#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?