/**************************************************************** filename: http_server.c author: xxxx function: Main file of http server Impliment the response of Get and Post mehtods history: created by xxxx date: 2014.01.03 *****************************************************************/ #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <strings.h> #include <unistd.h> #include <stdlib.h> #include <arpa/inet.h> #include <signal.h> #include <sys/wait.h> #include <sys/socket.h> #include <string.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/mman.h> #include "mime.h" #include "http_common.h" #include "http_webapp.h" // __DEBUG__ is debug tag #define BACK_LOG 50 #define SOCKLEN sizeof(struct sockaddr_in) // static int open_socket(struct sockaddr_in*); static int accept_client(int sockfd, struct sockaddr_in* paddr); static void wait_child(); static void write_response_body(int connfd, char* uri, int filesize); void process_request(int connfd); int main() { // char type[MAX_FILE_TYPE_LEN]=""; // get_mime_type("test.html",type); int sockfd = 0; int connfd = 0; struct sockaddr_in sockaddress; pid_t chld = 0; //struct sigaction sa; bzero(&sockaddress, sizeof(struct sockaddr_in)); signal(SIGCHLD, wait_child); //open sock if((sockfd=open_socket(&sockaddress)) == -1) { perror("open socket failed"); return -1; } //accept client connection while(1) { connfd = accept_client(sockfd, &sockaddress); #if __DEBUG__ printf("client accept [%d] ", connfd); #endif if((chld = fork()) > 0) { //root close(connfd); continue; }else if(chld == 0) { //childi process_request(connfd); close(sockfd); exit(0); } } return 0; } /*--------------------------------------------------------------- functionname: open_socket param: NA return: return sockfd on success, -1 on fail author: xxxx ----------------------------------------------------------------*/ static int open_socket(struct sockaddr_in* paddr) { int sockfd = 0; struct sockaddr_in sockaddress; bzero(&sockaddress, sizeof(sockaddress)); if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) return -1; sockaddress.sin_family = AF_INET; sockaddress.sin_port = htons(HTTP_PORT); inet_pton(AF_INET, "10.174.8.163", &(sockaddress.sin_addr)); if(bind(sockfd, (struct sockaddr*)(&sockaddress), sizeof(sockaddress)) == -1) return -1; if(listen(sockfd, BACK_LOG) == -1) return -1; *paddr = sockaddress; return sockfd; } /*--------------------------------------------------------------- functionname: accept_client param: NA return: return connfd on success, -1 on fail author: xxxx ----------------------------------------------------------------*/ static int accept_client(int sockfd, struct sockaddr_in* paddr) { socklen_t len = SOCKLEN; int connfd = 0; if(paddr != NULL) { connfd = accept(sockfd, (struct sockaddr*)(paddr), &len); }else { connfd = -1; } return connfd; } /*---------------------------------------------------------------- functionname: wait_child_exit param: NA return: NA author: xxxx TO KILL CHILD PROCESS, avoid ZOOBIE -----------------------------------------------------------------*/ static void wait_child() { int status = 0; while(waitpid(-1, &status, WNOHANG) > 0) { #if 0 printf("child process exit "); #endif } return; } /*----------------------------------------------------------------- functionname: process_request param: NA return: NA author: xxxx http request process history: create by xxxx, 2014.1.08, add simple abilities -----------------------------------------------------------------*/ void process_request(int connfd) { char request[MAX_REQUEST_LEN]; STR_REQUEST strreq; EN_MIME_TYPE type = MIME_ELSE; EN_REP_STATUS status = HTTP_END; STR_RESP response; long filesize = 0; FILE* fstream = NULL; bzero(&strreq, sizeof(STR_REQUEST)); bzero(request, sizeof(request)); bzero(&response, sizeof(STR_RESP)); if(recv(connfd, request, sizeof(request), 0) >0) { if(parse_request(request, &strreq) ==0) { #if __DEBUG__ printf("request:%s ", request); #endif get_mime_type(strreq.URI,&type); // file does not exist 404 if(file_exist(strreq.URI) == -1) { status = HTTP_NOT_FOUND; fstream = fopen(HTML_404, "rb"); }else { status = HTTP_OK; fstream = fopen(strreq.URI, "rb"); } filesize=get_file_size(fstream); #if __DEBUG__ printf("request file size = [%ld] ", filesize); #endif //response.data = (void*)malloc(filesize); //bzero(response.data, filesize); get_response_head(status,type,response.head,(int)filesize); #if __DEBUG__ printf("response head = [%s]", response.head); #endif //if(get_response_body(type, response.data, strreq.URI, filesize) == -1) // perror("fill response body failed"); #if __DEBUG__ //printf("response body = [%s] ", (char*)(response.data)); #endif fclose(fstream); send(connfd, response.head, strlen(response.head), 0); write_response_body(connfd, strreq.URI, (int)filesize); shutdown(connfd, SHUT_RD); close(connfd); } } } static void write_response_body(int connfd, char* uri, int filesize) { int fd =0; void* bodybuf = NULL; fd = open(uri, O_RDONLY, 0); bodybuf = mmap(NULL, filesize, PROT_READ, MAP_PRIVATE, fd, 0); send(connfd, bodybuf, filesize, 0); munmap(bodybuf, filesize); }