Code:
#include <time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <pthread.h>
#include <iostream>
#include <arpa/inet.h>
using namespace std;
extern void *serve(void *);
int main(int argc, char *argv[])
{
int port = htons(atoi(argv[1]));
int ssock, connsock, s;
struct sockaddr_in myaddr;
ssock = socket(AF_INET, SOCK_STREAM, 0);
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
myaddr.sin_port = port;
s=bind(ssock,(struct sockaddr *)&myaddr,sizeof(myaddr));
if(s < 0)
{
cerr << "cant bind\n"; exit(1);
}
listen(ssock,5);
pthread_t th;
int r;
while(true)
{
connsock=accept(ssock,0,0);
r=pthread_create(&th,0,serve,(void *)connsock);
}
}
void *serve(void *s)
{
int fin, fout, n;
int sock = (int)s, rc;
char buffer[2048],req[2048],resource[2048],protoc[2048],contentLengths[2048],dates[2048];
char fname[2048] ="pages/", logfile[2048], *exts, *hostip;
unsigned short port;
unsigned int cliaddrlen;
struct sockaddr_in myaddr, cliaddr;
pthread_detach(pthread_self());
rc = read(sock,buffer,2048);
n=sscanf(buffer,"%s %s %s", req, resource, protoc);
const char *reply1="HTTP/1.1 501 Method Not Implemented\r\nConnection: Close\r\n\r\n<h1>sorry</h1>\r\n";
const char *reply2="HTTP/1.1 200 OK\r\nConnection: Close\r\n";
const char *reply3="HTTP/1.1 404 File Not Found\r\nConnection: Close\r\n\r\n<h1>sorry</h1>\r\n";
const char *reply4="Content-Type: text/html\r\n\r\n";
const char *reply5="Content-type: image/jpeg\r\n\r\n";
const char *reply6="Content-type: text/plain\r\n\r\n";
const char *reply8="New connection\r\n\r\n";
const char *length="Content-Length: %d\r\n";
struct stat statbuf;
struct tm tmbuf;
time_t mtime;
fout=open ("logfile",O_APPEND|O_WRONLY|O_CREAT,0644);
time(&mtime);
hostip = inet_ntoa(cliaddr.sin_addr);
port = ntohs(cliaddr.sin_port);
gmtime_r(&mtime, &tmbuf);//returns the time the connection was made and the type of request.
sprintf(logfile,req,protoc ,2048 ,"---Connection time: %A, %d-%b-%y %T GMT\r\n",&tmbuf);
write(fout, logfile, strlen(logfile));;
close (fout);
if(strcmp(req,"GET")==0) // depending on the request it prints out the correct protocol response
{
strcat(fname,resource+1);
if(access(fname,F_OK) <0)
{
write(sock,reply3,strlen(reply3));
}
else
{
write(sock,reply2,strlen(reply2));
exts = strrchr(fname, '.');
if(strcmp(exts,".cgi")==0)
{
int pid;
pid = fork();
if (fork == 0)
{
dup2(sock,0);
dup2(sock,1);
execlp(fname, fname,0);
exit(2);
}
}
else
{
stat(fname,&statbuf);// shows the content-length of the file that been sent by the response.
sprintf(contentLengths,length,statbuf.st_size);
write(sock,contentLengths,strlen(contentLengths));
mtime = statbuf.st_mtime;//Shows the last modified time if the file exists.
gmtime_r(&mtime, &tmbuf);
strftime(dates,2048 ,"Last-Modified: %A, %d-%b-%y %T GMT\r\n",&tmbuf);
write(sock,dates,strlen(dates));
// checks the extension of the name of the requested file eg. html.
if(strcmp(exts,"jpg")==0 || strcmp(exts,"jpeg")==0)
{
write(sock,reply5,strlen(reply5));
}
if (strcmp(exts, "txt")==0)
{
write(sock,reply6,strlen(reply6));
}
else
{
write(sock,reply4,strlen(reply4));
}
fin=open(fname,O_RDONLY);
rc = read(fin, buffer, 2048);
while(rc > 0)
{
write(sock, buffer, rc);
rc = read(fin, buffer, 2048);
}
close(fin);
}
}
}
else
{
write(sock,reply1,strlen(reply1));
}
close(sock);
pthread_exit(0);
}