Exemplo n.º 1
0
/*******************************************************************************
* Function Name  	:  HandleHttpClient.  
* Description    	:  handle http request.
* Input          		:  ClientSocket:Http Client socket.
* Return         	:  None.
*******************************************************************************/
static void HandleHttpClient(int index)
{
	int NumOfBytes;
	httpToken_struct httpToken ={0,0,0};
	char *p_auth;


    msleep(200); // sleep 200 ms, just incase http request fregment.
	NumOfBytes = recv(index, httpRequest, HTTP_DATA_MAX_LEN, 0);
	if (NumOfBytes < 0) {
		return;
	} else if (NumOfBytes == 0) {
		return;
	}

	httpRequest[NumOfBytes] = '\0';
	if(!HTTPParse(httpRequest,&httpToken)) 
		goto EXIT;;//http request header error

    p_auth = strstr(httpToken.pToken2, auth_str);
	if (p_auth == NULL) { // un-authrized
        send_http_data(index, (char*)authrized, strlen(authrized));
        goto EXIT;
	} else {
        p_auth += strlen(auth_str);
        if (*p_auth != 0x0d) {
            send_http_data(index, (char*)authrized, strlen(authrized));
            goto EXIT;
        }
    }	
		
	if(!strcmp(httpToken.pToken1, "GET"))  
	{
    if(!strncmp(httpToken.pToken2, "/system.htm", strlen("/system.htm")))  {
			send_system_page(index);
		} 
	  else if(!strncmp(httpToken.pToken2, "/ ", 2))  {
			send_system_page(index);
		} else {
			send_http_data(index, (char *)not_found, strlen(not_found));
		}
	}
	else if(!strcmp(httpToken.pToken1, "POST"))  
	{
		if(!strncmp(httpToken.pToken2, "/update.htm", strlen("/update.htm")))  {
			get_update_post(index, httpToken.pToken2, NumOfBytes - (httpToken.pToken2-httpRequest));
		} 
		if(!strncmp(httpToken.pToken2, "/settings.htm", strlen("/settings.htm")))  {
			get_settings_post(index, httpToken.pToken2, NumOfBytes - (httpToken.pToken2-httpRequest));
		} 

	}

EXIT:
    
	return;
}
Exemplo n.º 2
0
static void send_system_page(int index)
{
	char *body;
	u32 NumOfBytes;	
	
#define FORMAT_POST_STR sprintf(body, systemPage, firmwareVersion,\
						configParas.wifi_ssid, configParas.wifi_key);

	memset(httpRequest,0,HTTP_DATA_MAX_LEN);
	body = httpRequest;
	FORMAT_POST_STR;
	sprintf(httpRequest, headerPage, strlen(body)); 	// recalute the body length.
	body = httpRequest+strlen(httpRequest);
	FORMAT_POST_STR;
	NumOfBytes = strlen(httpRequest);

	send_http_data(index, httpRequest, NumOfBytes);
}
Exemplo n.º 3
0
void save_reset_Response(u8 result, int index)
{
	if(result == TRUE)
	{
		sprintf(httpRequest, HTTPSaveResponse, 
		strlen(SaveResponseSucc), SaveResponseSucc);
		updateConfig(&configParas);
	}
	else if(result == FALSE)
	{
		sprintf(httpRequest, HTTPSaveResponse, 
				strlen(SaveResponseError), SaveResponseError);
		
	} else if(result == 2)
	{
		sprintf(httpRequest, HTTPSaveResponse, 
				strlen(ResponseReset), ResponseReset);
		SetTimer(3000, delay_reload);
	}

	send_http_data(index, httpRequest, strlen(httpRequest));
}
Exemplo n.º 4
0
void
http_server_main_loop_epoll_et(int listenedfd)
{
	int i = 0;
	int nready = 0;
	int connfd = -1;
	int ret = 0;
	struct sockaddr_in peeraddr;
	socklen_t peerlen = sizeof(peeraddr);
	http_data h_info;

	//建立epoll机制
	int epollfd = epoll_create1(EPOLL_CLOEXEC);
	struct epoll_event event;
	//采用et模式的时候所有加入epoll的套接字都要采用非阻塞的方式
	//如果文件描述符是阻塞的,那么读或者写操作会因为没有后续的事
	//件而一直处于阻塞状态(饥渴状态)
	activate_nonblock(listenedfd);
	event.data.fd = listenedfd;
	event.events = EPOLLIN | EPOLLET;//采用边沿触发的方式
	epoll_ctl(epollfd,EPOLL_CTL_ADD,listenedfd,&event);
	struct epoll_event events[MAX_FD_SETSIZE];
	while(1) {
		nready = epoll_wait(epollfd,events,MAX_FD_SETSIZE,-1);
		if(-1 == nready) {
			if(EINTR == errno) {
				continue;
			}
			perror("epoll_wait");
			break;
		}
		if(0 == nready) {
			continue;
		}

		//每次返回的事件都会保存到events数组中所以可以直接来进行判断
		for(i = 0;i < nready;++i) {
			if(events[i].data.fd == listenedfd) {
				while(1) {
					//accept可能会有多次连接(特别是在进行并发测试的时候)
					//如果不加,可能会导致write出现EPIPE的错误可能是由于
					//epoll的ET模式的机制,如果同时到达的accept不能处理
					//完,那么有些就会饿死在epoll中
					peerlen = sizeof(peeraddr);
					connfd = accept(listenedfd,
						(struct sockaddr *)&peeraddr,&peerlen);
					if(connfd < 0) {
						if(EAGAIN == errno || EWOULDBLOCK == errno) {
							break;
						} else {
							perror("accept");
							return;
						}
					}
					DEBUG_PRINT("ip = %s port = %d\n",
						inet_ntoa(peeraddr.sin_addr),
						ntohs(peeraddr.sin_port));
					//设定为非阻塞套接字
					activate_nonblock(connfd);
					event.data.fd = connfd;
					event.events = EPOLLIN | EPOLLET;
					epoll_ctl(epollfd,EPOLL_CTL_ADD,connfd,&event);
				}
			} else if(events[i].events & EPOLLIN) {
				connfd = events[i].data.fd;
				if(connfd < 0) {
					continue;
				}
				//业务逻辑代码
				bzero(&h_info,sizeof(h_info));
				h_info.data_len = sizeof(h_info.buf);
				//处理接收到的数据
				ret = read_http_data(connfd,&h_info);
				if(ret < 0) {
					if(EAGAIN == errno || EWOULDBLOCK == errno) {
						continue;
					} else {
						perror("read_http_data");
						return;
					}
				}
				if(0 == ret) {
					//client close
					DEBUG_PRINT("client close\n");
					//FD_CLR(client[i],&rfset);
					close(connfd);
					//从epoll中删除代码
					event = events[i];
					epoll_ctl(epollfd,EPOLL_CTL_DEL,connfd,&event);
					continue;
				}
				//解析数据填充数据类型结构体
				ret = analysis_http_data(&h_info);
				ret = send_http_data(connfd,&h_info);
				if(ret < 0) {
					//这里一般来说会有EPIPE的错误,但是在其它很多的程序中,
					//对这个错误似乎是无法接受的直接报错退出
					perror("send_http_data");
					return;
				}
			}
		}
	}
}
Exemplo n.º 5
0
void
http_server_main_loop_poll(int listenedfd)
{
	//
	struct pollfd client[MAX_FD_SETSIZE];
	int i = 0,maxinx = 1;
	for(i = 0;i < MAX_FD_SETSIZE;++i) {
		client[i].fd = -1;
	}
	int nready = 0;
	int connfd = -1;
	int ret = 0;
	struct sockaddr_in peeraddr;
	socklen_t peerlen = sizeof(peeraddr);

	http_data h_info;

	client[0].fd = listenedfd;
	client[0].events = POLLIN;
	while(1) {
		nready = poll(client,maxinx,-1);
		if(-1 == nready) {
			if(EINTR == errno) {
				continue;
			}
			perror("poll");
			break;
		}
		if(0 == nready) {
			continue;
		}
		if(client[0].revents & POLLIN) {
			//表明监听套接字有可读的事件
			peerlen = sizeof(peeraddr);
			connfd = accept(listenedfd,
				(struct sockaddr *)&peeraddr,
							&peerlen);
			if(-1 == connfd) {
				perror("accept");
				break;
			}
			for(i = 0;i < MAX_FD_SETSIZE;++i) {
				if(client[i].fd < 0) {
					client[i].fd = connfd;
					if(i > maxinx) {
						maxinx = i + 2;
					} else if(1 == maxinx) {
						maxinx = 2;
					}
					break;
				}
			}
			if(MAX_FD_SETSIZE == i) {
				fprintf(stderr,"too many clients\n");
				exit(EXIT_FAILURE);
			}
			DEBUG_PRINT("ip = %s port = %d\n",
				inet_ntoa(peeraddr.sin_addr),
				ntohs(peeraddr.sin_port));
			//设置好这个套接字要关心的事件
			client[i].events = POLLIN;
			if(--nready <= 0) {
				continue;
			}
		}
		for(i = 1;i < maxinx;++i) {
			//遍历其它的套接字的事件接收情况
			if(-1 == client[i].fd) {
				continue;
			}
			if(client[i].events & POLLIN) {
				//业务代码处理
				bzero(&h_info,sizeof(h_info));
				h_info.data_len = sizeof(h_info.buf);
				//处理接收到的数据
				ret = read_http_data(client[i].fd,&h_info);
				if(ret < 0) {
					perror("read_http_data");
					return;
				}
				if(0 == ret) {
					//client close
					DEBUG_PRINT("client close\n");
					//FD_CLR(client[i],&rfset);
					close(client[i].fd);
					client[i].fd = -1;
				} else {
					//解析数据填充数据类型结构体
					ret = analysis_http_data(&h_info);
					ret = send_http_data(client[i].fd,&h_info);
					if(ret < 0) {
						perror("send_http_data");
						return;
					}
				}
			}
			if(--nready <= 0) {
				break;
			}
		}
	}
}
Exemplo n.º 6
0
//select方式来实现IO复用处理发送
//这个select主要坑的地方在于每次select的文件描述符集合收到事件解除阻塞然后进入到业务处理函数中处理完成后,
//必须要重新初始化一边文件描述符集合,然后把要监控的IO重新加入一遍。
//否则文件描述符集合不会再接收新的信号
//上述原因正是导致前期实现的时候总是出现select阻塞导致客户端老是收不到数据的原因。
void
http_server_main_loop_select(int listenedfd)
{
	//select方式来实现IO复用处理发送
	//首先是设定好一个文件描述符的集合,管理收到数据的文件描述符
	fd_set rfset;
	FD_ZERO(&rfset);
	FD_SET(listenedfd,&rfset);

	int nready = 0;
	int maxfd = listenedfd;
	int connfd = -1;
	int client[MAX_FD_SETSIZE] = {[0 ... MAX_FD_SETSIZE - 1] = -1};
	int i = 0;
	int maxinx = 1;
	int ret = 0;

	struct sockaddr_in peeraddr;
	socklen_t peerlen = sizeof(peeraddr);

	http_data h_info;
	while(1) {
		//DEBUG_PRINT("will select!maxfd %d\n",maxfd);
		nready = select(maxfd + 1,&rfset,NULL,NULL,NULL);
		//DEBUG_PRINT("after select!\n");
		if(nready < 0) {
			perror("select");
			break;
		}
		if(nready == 0) {
			continue;
		}
		//否则就是接收到了数据需要进行判断
		if(FD_ISSET(listenedfd,&rfset)) {
			peerlen = sizeof(peeraddr);
			connfd = accept(listenedfd,
				(struct sockaddr *)&peeraddr,&peerlen);
			if(connfd < 0) {
				perror("accept");
				break;
			}
			DEBUG_PRINT("ip = %s port = %d\n",
				inet_ntoa(peeraddr.sin_addr),
					ntohs(peeraddr.sin_port));
			//接收到了新的连接套接字就要将其加入到文件集合中进行监听
			FD_SET(connfd,&rfset);
			//
			for(i = 0;i < MAX_FD_SETSIZE;++i) {
				if(-1 == client[i]) {
					client[i] = connfd;
					if(i >= maxinx) {
						maxinx = i + 1;
					}
					break;
				}
			}
			if(MAX_FD_SETSIZE == i) {
				fprintf(stderr,"too many clients\n");
				exit(EXIT_FAILURE);
			}
			if(connfd > maxfd) {
				maxfd = connfd;
			}
			//说明不需要处理了,因为已经处理完了
			if(--nready <= 0) {
				//重新进入select之前一定要保证文件描述符集合被重新初始化
				maxfd = reset_fd_set_and_maxfd(listenedfd,maxinx,client,&rfset);
				continue;
			}
		}
		//循环判断连接套接字是否有数据收到
		for(i = 0;i < maxinx;++i) {
			if(client[i] < 0) {
				continue;
			}
			if(FD_ISSET(client[i],&rfset)) {
				bzero(&h_info,sizeof(h_info));
				h_info.data_len = sizeof(h_info.buf);
				//处理接收到的数据
				ret = read_http_data(client[i],&h_info);
				if(ret < 0) {
					perror("read_http_data");
					return;
				}
				if(0 == ret) {
					//client close
					DEBUG_PRINT("client close\n");
					//FD_CLR(client[i],&rfset);
					close(client[i]);
					client[i] = -1;
				} else {
					//解析数据填充数据类型结构体
					ret = analysis_http_data(&h_info);
					ret = send_http_data(client[i],&h_info);
					if(ret < 0) {
						perror("send_http_data");
						return;
					}
				}
				
				if(--nready <= 0) {
					break;
				}
			}
		}
		maxfd = reset_fd_set_and_maxfd(listenedfd,maxinx,client,&rfset);
	}
}
Exemplo n.º 7
0
static void get_update_post(int index, char *postdata, int len)
{
	static const char endline[] = {'\r', '\n', '\r', '\n'};
	static const char lengthstr[] = "Content-Length: ";
	static const char boundarystr[] = "boundary=";
	char *boundcp, *boundary, *p;
	char *read_buffer = postdata, *end_pos = NULL, *lengthpos;
	int read_buffer_size = len, time=5000;
	int bytes_received, read_len, content_len = 0, total_read;
	const char *resp;
	u32 addr = UPDATE_START_ADDRESS;
	
	/* Firmware update: OTA from webserver*/
    setsockopt(index,0, SO_RCVTIMEO, &time, 4);

    /* Get the content length & boundary & begin of content data */
    do {
        end_pos = (char*) memmem(read_buffer, read_buffer_size, endline, sizeof(endline));

        if ( ( lengthpos = (char*) memmem( read_buffer,  read_buffer_size, lengthstr, strlen( lengthstr )) ) != NULL )
        {
            content_len = atoi(lengthpos + sizeof( lengthstr)-1);
        }
        if (( boundary = (char*) memmem( read_buffer,  read_buffer_size, boundarystr, strlen(boundarystr) )) != NULL )
        {
            boundary += strlen(boundarystr);
            p = boundary;
            while(*p != 0x0d)
                p++;
            *p++ = 0; 
            // now, we have found out the boundary, copy out.
            boundcp = (char*)malloc(strlen(boundary)+1);
            if (boundcp != NULL) {
                strcpy(boundcp, boundary);
            }
        }
        
        if (end_pos == NULL)
        {
            read_buffer = httpRequest;
            bytes_received = recv(index, httpRequest, HTTP_DATA_MAX_LEN, 0 );
            if ( bytes_received <= 0 )
            {
                break;
            }
            else
            {
                total_read += bytes_received;
                read_buffer_size = bytes_received;
            }
        }

    } while ( end_pos == NULL );
    if (boundcp == NULL || content_len == 0) {
        resp = systemResponseError;
        goto EXIT;
    }

    end_pos += sizeof(endline);
    read_buffer_size = read_buffer_size - (end_pos-read_buffer);
    content_len -= read_buffer_size;
    read_buffer = end_pos;
    /* Get the begin of file data and write to flash */
    do {
        end_pos = (char*)memmem(read_buffer, read_buffer_size, endline, sizeof(endline));
        
        if (end_pos == NULL)
        {
            read_buffer = httpRequest;
            bytes_received = recv(index, httpRequest, HTTP_DATA_MAX_LEN, 0 );
            if ( bytes_received <= 0 )
            {
                break;
            }
            else
            {
                content_len -= bytes_received;
                read_buffer_size = bytes_received;
                if (content_len <= 0)
                    break;
            }
        }

    } while ( end_pos == NULL );
    if (end_pos == NULL) {
        resp = systemResponseError;
        goto EXIT;
    }
    
    SetTimer(6000, delay_reload); // whether success or not, need reload system to use bootload erase NEW Image flash.
    FLASH_If_Init();
    end_pos += sizeof(endline);
    read_buffer_size = read_buffer_size - (end_pos-read_buffer);
    if (read_buffer_size > 0) {
			  FLASH_If_Write(&addr, (void *)end_pos, read_buffer_size);
    }

    content_len -= strlen(boundcp) - 4; // last string is '--'+boudnary+'--'
    /* Recv file and write to flash, if it's last package, find the end of file to write */
    while(content_len > 0) {
        if (content_len > HTTP_DATA_MAX_LEN)
            read_len = HTTP_DATA_MAX_LEN;
        else
            read_len = content_len;
        
        bytes_received = recv(index, httpRequest, read_len, 0 );
        if ( bytes_received <= 0 )
        {
            break;
        }
        
				FLASH_If_Write(&addr, (void *)httpRequest, bytes_received);    
        content_len -= bytes_received;
    }
    
    if (content_len == 0) {        
      memset(&configParas, 0, sizeof(boot_table_t));
    	configParas.bootTable.length = addr - UPDATE_START_ADDRESS;
    	configParas.bootTable.start_address = UPDATE_START_ADDRESS;
    	configParas.bootTable.type = 'A';
    	configParas.bootTable.upgrade_type = 'U';
			updateConfig(&configParas);
      resp = systemResponseSucc;
    } else
      resp = systemResponseError;
EXIT:
    FLASH_Lock();
    sprintf(httpRequest, HTTPSaveResponse, 
			strlen(resp), resp);
    send_http_data(index, httpRequest, strlen(httpRequest));
}