Select Git revision
search_algorithm.py
server.c 9.00 KiB
/* Hanbin Li 789786
login id: hanbinl1
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <pthread.h>
#define BACKLOG 10 // how many pending connections queue will hold
#define MAXDATASIZE 1000
//Global variables used only for setiing the command line root from the user.
char demoRpath[100];
char *rootPath;
//*********************************************************************
//---------------------------read request line Method------------------
#if 1
// Function to read each line of the GET reuqest
int http_readline(int sock, char *buf, int maxlen)
{
int n = 0;
char *p = buf;
while (n < maxlen - 1) {
char c;
int rc = read(sock, &c, 1);// Reading from a socket and copying it to a integer
if (rc == 1) {
/* Stop at \n and strip away \r and \n. */
if (c == '\n') {
*p = 0; /* null-terminated */
return n;
} else if (c != '\r') {
*p++ = c;
n++;
}
} else if (rc == 0) {
return -1;
/* EOF */
} else if (errno == EINTR) {
continue;
/* retry */
} else {
return -1;
/* error */
}
}
return -1; /* buffer too small */
}
#endif
/*=========================== Readline- End ===========================*/
//*********************************************************************
//---------------------------httpRequest Method------------------------
void* httpRequest(void* data)
{
int th,r,b=0,fileOK=0;
char *req,tmp_var[50],doc_root[100],demoRpath[100];
char buf[MAXDATASIZE], *filePath,*ftype,*type;
char statusLine[100]="HTTP/1.0";
char contentTypeLine[100]="Content-type: ";
char entityBody[100]="<html>";
FILE *fp;
/*
variable description
-------------------------------------------------------------------
int r -----> Used to save the readline return value.
int b -----> Used in iteration in while loop.
char *req -----> Used to save the returned buffer line.
char tmp_var[] -----> Used to check empty space and empty space.
char doc_root -----> Used to save the root location taken from the user.
char demoRpath[] -----> Used to commandline arugument passed for root address
char buf[] -----> Used to save the GET request from client.
char *filePath -----> Used to save the file path requested in root folder.
char *ftype -----> Used to save the file file.
char *type -----> Used to return MIME type.
*/
th=*((int *)data);
int a=0;
r=http_readline(th,buf,sizeof(buf));//
if(r>0) {
req=buf;
} else {
perror("[ERROR:] Failed to read.\n");
exit(1);
}
// Condition runs till it encounters an empty space
while(req[b]!=' ') {
tmp_var[b]=req[b++];
}
//copying the command line entered root location to rootPath to make it rootlocation
strcpy(demoRpath,rootPath);
if((strcmp(tmp_var,"GET"))==0)// Comparing the temporary array to check the string
{
strcpy(doc_root,demoRpath);
fprintf(stderr,"\nDocument Root\n\n\t");
puts(doc_root);
// Extract the file name
char *filePath, *fl1, *fl2;
fl1 = strpbrk(req,"/");
fl2 = strtok(fl1," ");
filePath = strpbrk(fl2, "/");
// When GET request sends "/" we map to "/index.html"
if (strcmp(filePath,"/")==0){
strcpy(filePath,strcat(doc_root,"/index.html"));
} else {
strcpy(filePath, strcat(doc_root,filePath));
printf("\nRequest File path\n\n\t");
puts(filePath);
}
//Open the requested file.
fp=fopen(filePath,"r");
printf("\nRequested File status\n\n\t");
if(fp!=NULL){
fileOK=1;
printf("Requested file exist in the server.\n");
} else {
printf("Requested file does exist in the server.\n");
}
if (fileOK==1) {
//fclose (fp);
int z ='.';
ftype=strrchr(filePath,z);
printf("\nRequested file is of type:\t");
puts(ftype);
// MIME recognition
if((strcmp(ftype,".html"))==0){
type="text/html";
} else if (strcmp(ftype, ".jpg") == 0) {
type= "image/jpeg";
} else if (strcmp(ftype, ".css") == 0) {
type = "text/css";
} else if (strcmp(ftype, ".js") == 0) {
type = "text/js";
} else {
type= "application/octet-stream";
}
//send status line and the content type line
strcpy(statusLine,strcat(statusLine,"200 OK"));
strcpy(statusLine,strcat(statusLine,"\r\n"));
strcpy(contentTypeLine,strcat(contentTypeLine,type));
strcpy(contentTypeLine,strcat(contentTypeLine,"\r\n"));
} else {
strcpy(statusLine,strcat(statusLine,"404 Not Found"));
strcpy(statusLine,strcat(statusLine,"\r\n"));
//send a blank line to indicate the end of the header lines
strcpy(contentTypeLine,strcat(contentTypeLine,"NONE"));
strcpy(contentTypeLine,strcat(contentTypeLine,"\r\n"));
//send the entity body
strcpy(entityBody,strcat(entityBody,"<HEAD><TITLE>404 Not Found</TITLE></HEAD>"));
strcpy(entityBody,strcat(entityBody,"<BODY>Not Found</BODY></html>"));
strcpy(entityBody,strcat(entityBody,"\r\n"));
}
//send the header.
if ((send(th, statusLine, strlen(statusLine), 0) == -1) ||
(send(th, statusLine, strlen(statusLine),0) == -1) ||
(send(th,"\r\n", strlen("\r\n"), 0) == -1)) {
perror("Failed to send bytes to client");
}
if (fileOK) {
wchar_t read_char[1];
while((read_char[0]=fgetc(fp))!=EOF) {
if(send(th,read_char,sizeof(char),0) == -1){
perror("Failed to send bytes to client");
}
}
} else {
if (send(th, entityBody, 100, 0) == -1){
perror("Failed to send bytes to client");
}
}
close(th); // Close the connection.
pthread_exit(NULL); //Existing from the threads.
} else {
printf("Warning message\n");
}
}
//****************************************************************************************************************
//Main Method------------------------------------------------------------------
int main (int argc, char **argv)
{
int sockfd, new_fd, portno; // listen on sock_fd, new connection on new_fd
struct sockaddr_in serv_addr, cli_addr;
socklen_t clilen;
pthread_t p_thread[3000];
pthread_attr_t attr_t;// Attritube to thread
pthread_attr_init(&attr_t);// Initilizing the attribute
pthread_attr_setdetachstate(&attr_t, PTHREAD_CREATE_DETACHED); //Creating the tread in detach state
int thr_id,i=0;
// check command line
if (argc != 3)
{
fprintf(stderr,"ERROR, usage: server [port number] [path]\n");
exit(1);
}
//Create the parent socket.
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
perror("ERROR opening socket");
exit(1);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
rootPath = argv[2];
//Build the server's Inernet address.
// bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET; // host byte order
serv_addr.sin_port = htons(portno); // short, network byte order
serv_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
// Bind address to the socket */
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
{
perror("ERROR on binding");
exit(1);
}
//Make this socket ready to accept connection requests.
if (listen(sockfd, BACKLOG) == -1) {
perror("listen");
exit(1);
}
clilen = sizeof(cli_addr);
while(1)
{ // main accept() loop
new_fd = accept( sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (new_fd < 0)
{
perror("ERROR on accept");
exit(1);
}
//Creates threads.
thr_id = pthread_create(&p_thread[i++],&attr_t,httpRequest,(void*)&new_fd);
pthread_attr_destroy(&attr_t);
}
return 0;
}