// CREDITS : F. Harrouet, www.enib.fr/~harrouet
//======================================================================
#include "main.h"
#include "httpServerLib.h"
#define BUFFER_SIZE 0x1000
//======================================================================
void * dialogThread(void *arg)
{
pthread_detach(pthread_self());
char buffer[BUFFER_SIZE];
Request *req=(Request *)arg;
//---- receive and analyse HTTP request line by line ----
bool first=true;
for(;;)
{
if(recvLine(req->sock,buffer,BUFFER_SIZE)<=0) { break; }
printf("%s",buffer);
if(first)
{
first=false;
sscanf(buffer,"%s %s",req->requestMethod,req->requestUri);
}
else if(!strcmp(buffer,"\n")||!strcmp(buffer,"\r\n"))
{
break;
}
}
//---- prepare and send HTTP reply ----
int r=sprintf(buffer,"HTTP/1.0 200 OK\n"
"Connection: close\n"
"Content-Type: text/html\n"
"\n"
"
\n" // Text displayed in the web browser :
"200 - OK
\n"
"method: %s
\n"
"uri: %s
\n"
"hello world\n"
"\n",
req->requestMethod,
req->requestUri);
sendAll(req->sock,buffer,r);
destroyRequest(req);
return (void *)0;
}
//======================================================================
// MAIN
//======================================================================
int main(int argc, char **argv)
{
//---- avoid exiting on broken client connection (ignore SIGPIPE) ----
struct sigaction sa;
memset(&sa,0,sizeof(struct sigaction));
sa.sa_handler=SIG_IGN;
if(sigaction(SIGPIPE,&sa,(struct sigaction *)0)==-1)
{ perror("sigaction"); exit(1); }
//---- check command line arguments ----
if(argc!=2)
{ fprintf(stderr,"usage: %s http_port\n",argv[0]); exit(1); }
//---- extract local port number ----
int httpPortNumber;
if(sscanf(argv[1],"%d",&httpPortNumber)!=1)
{ fprintf(stderr,"invalid port %s\n",argv[1]); exit(1); }
//---- multithreaded TCP server launching dialogThread() ----
//---- create HTTP listen socket ----
int httpSocket=socket(PF_INET,SOCK_STREAM,0);
if(httpSocket==-1)
{ perror("socket"); exit(1); }
// ... avoiding timewait problems (optional)
int on=1;
if(setsockopt(httpSocket,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(int))==-1)
{ perror("setsockopt"); exit(1); }
// ... bound to any local address on the specified port
struct sockaddr_in myAddr;
myAddr.sin_family=AF_INET;
myAddr.sin_port=htons(httpPortNumber);
myAddr.sin_addr.s_addr=htonl(INADDR_ANY);
if(bind(httpSocket,(struct sockaddr *)&myAddr,sizeof(myAddr))==-1)
{ perror("bind"); exit(1); }
// ... listening connections
if(listen(httpSocket,10)==-1)
{ perror("listen"); exit(1); }
for(;;)
{
//---- accept new HTTP connection ----
struct sockaddr_in fromAddr;
socklen_t len=sizeof(fromAddr);
int dialogSocket=accept(httpSocket,(struct sockaddr *)&fromAddr,&len);
if(dialogSocket==-1)
{ perror("accept"); exit(1); }
printf("new HTTP connection from %s:%d\n",
inet_ntoa(fromAddr.sin_addr),ntohs(fromAddr.sin_port));
//---- start a new dialog thread ----
pthread_t th;
if(pthread_create(&th,(pthread_attr_t *)0, dialogThread,createRequest(dialogSocket)))
{ fprintf(stderr,"cannot create thread\n"); exit(1); }
}
close(httpSocket);
return 0;
}
//^^^^^^^^^^^^^^^^^^^^^^^^^^ EOF ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^