/****************************************************************
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]\n ", 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\n");
#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\n", 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]\n", 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]\n", (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);
}