I have created a simple server that host html that has css. Please make sure if ur testing then change the paths relative to ur system in listhell.c in respond_main(..) function.
The html file has to be named as html9.html and css has to be named as style9.css should be path to ../project directory/css directory. this is the code along with makefile
This is main function file server.c
#include "headers/accept.h"
int main()
{
pthread_t thread_css;
pthread_t thread_html;
pthread_t thread_get;
int server_fd, new_socket, valread;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[1024] = {0};
char *hello = "Hello from server";
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
printf("socket failed\n");
exit(EXIT_FAILURE);
}
printf("server_fd = %d\n",server_fd);
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,
&opt, sizeof(opt)))
{
printf("setsockopt\n");
exit(EXIT_FAILURE);
}
int state = 1;
if(setsockopt(server_fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state)))
{
printf("TCP CORK\n");
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( PORT );
// Forcefully attaching socket to the port 8080
if (bind(server_fd, (struct sockaddr *)&address,
sizeof(address))<0)
{
printf("bind failed\n");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0)
{
printf("listen\n");
exit(EXIT_FAILURE);
}
accept1(server_fd,address,addrlen);
return 0;
}
this is the file that contains linux socket accept
function call accept.c
#include "headers/accept.h"
#define BUFFER 1024+1
int check_if_t(char *buffer,int valread,int *f)
{
int i=0;
while(i<BUFFER)
{
printf("%c",*(buffer+i));
if(*(buffer+i)=='\r')
{
*f=1;
printf("***************************************************************************\n");
return i;
}
i++;
}
return i;
}
void* handle_request(void *arg)
{
//printf("\n");
struct connection *con_obj=malloc(sizeof(struct connection));
if(con_obj!=NULL)
{
//con_obj->server_fd=(int*)arg;
con_obj=(struct connection *)arg;
//printf("new_socket get thread : %d\n",*(con_obj->new_socket));
char *str_array=NULL;
str_array=malloc(BUFFER+1);
str_array[0]='\0';
char buffer[BUFFER] = {0};
int x=0;
int check_tp=0;
int j=0;
while(x<BUFFER)
{
int valread=read(*(con_obj->new_socket),&buffer[x],BUFFER);;
// printf("Socket Buffer read valread = %d \n %.*s",(valread-1),(valread-1),buffer);
int f=0;
check_tp=check_if_t(buffer,(BUFFER),&f);
//printf("check_tp = %d\n",check_tp);
if(f==1)
{
strncpy(&str_array[j],&buffer[j],check_tp);
j=j+check_tp;
str_array[j]='\0';
//printf("--->\n");
//printf("j = %d\n",j);
//printf("%.*s\n",j,str_array);
break;
}
if(str_array!=NULL)
strncpy(&str_array[j],&buffer[j],check_tp);
j=j+check_tp;
x=x+check_tp;
}
x=0;
if(str_array!=NULL)
{
if(strlen(str_array)>0)
{
//printf("printing first line = %s | length = %zu j = %d\n ",str_array,strlen(str_array),j);
pthread_t thread_process;
con_obj->request_line=malloc(sizeof(char)*j);
if(con_obj->request_line==NULL)
{
while(1)
{
printf("handle_request -- heap problem at line 80: con_obj->request_line=malloc(sizeof(char)*j); \n");
}
}
if(j>=BUFFER)
{
free(con_obj->request_line);
printf("check line 89 handle_request\n");
//exit(0);
j=BUFFER-1;
con_obj->request_line[j]='\0';
close(*(con_obj->new_socket));
free(con_obj);
return (void*)0;
}
memcpy((con_obj->request_line),str_array,sizeof(char)*j);
con_obj->request_line_size=j;
pthread_create(&thread_process, NULL, process, (void *)con_obj);
}
else{
//printf("str_array length not found = %zu\n",strlen(str_array));
}
free(str_array);
//
}
}
else
{
printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
printf("No space for malloc on heap\n");
}
return (void*)0;
}
void accept1(int server_fd,struct sockaddr_in address,int addrlen)
{
while(1)
{
int new_socket;
if ((new_socket = accept(server_fd, (struct sockaddr *)&address,
(socklen_t*)&addrlen))<0)
{
perror("accept");
exit(EXIT_FAILURE);
}
//printf("new_socket just created = %d\n",new_socket);
pthread_t thread_get;
struct connection *con_obj=malloc(sizeof(struct connection));
if(con_obj!=NULL)
{
con_obj->new_socket=&new_socket;
con_obj->address=address;
//printf("%d hello\n",*(con_obj->new_socket));
pthread_create(&thread_get, NULL, handle_request, (void *)con_obj);
}
else
{
printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
printf("No space for malloc on heap\n");
}
int state = 0;
if(setsockopt(server_fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state)))
{
printf("TCP CORK\n");
}
state = 1;
if(setsockopt(server_fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state)))
{
printf("TCP CORK\n");
}
//printf("After Thread creation\n");
}
}
this is process.c
#include <stdio.h>
#include "headers/accept.h"
//fetch null terminated string values
// void get_dirs_file(char *path, char **dirs,char **file)
// {
// printf("getting directories and file for path = %s \n",path);
//
// }
int handle_process(struct connection *con_obj,char **path,char **request_type)
{
int i=0;
request_type[0]='\0';
int method=0;
while(i<(con_obj->request_line_size))
{
//printf("%c",(con_obj->request_line[i]));
if(strncmp(&(con_obj->request_line[i]),"GET",3)==0)
{
method=3;
*request_type=malloc(sizeof(char)*4);
strncpy(*request_type,"GET",sizeof(char)*4);
char *temp=con_obj->request_line+4;
if(strncmp(temp,"/ ",2)==0)
{
*path=malloc(sizeof(char)*strlen("html9.html"));
strncpy(*path,"html9.html",strlen("html9.html")+1);
break;
}
if(strncmp(temp,"/add?",sizeof(char)*5)==0)
{
int j=0;
while(j<strlen(temp))
{
if(temp[j]==' ')
{
break;
}
j++;
}
*path =malloc(sizeof(char)*j+1);
strncpy(*path,temp,sizeof(char)*j);
(*(path+j))='\0';
//tm((&path));
//printf("hello line now -------> %s\n",*path);
break;
}
if(strncmp(temp,"/css/",sizeof(char)*5)==0)
{
int j=0;
while(j<strlen(temp))
{
if(temp[j]==' ')
{
break;
}
j++;
}
*path=malloc(sizeof(char)*j+1);
strncpy(*path,temp,sizeof(char)*j);
(*(path+j))='\0';
//printf("hello line now -------> %s\n",*path);
} //return strlen("GET");
}
i++;
}
printf("hello line now -------> path = %s request_type = %s\n",*path,*request_type);
if(method==0)
return 0;
return strlen(*request_type);
}
void *process(void *p)
{ //printf("hello in process thread\n");
int r=0;
struct connection *con_obj=malloc(sizeof(struct connection));
if (con_obj != NULL)
{
printf("\n\n");
printf("------------------------------------------------------------------------------------\n");
con_obj=(struct connection *)p;
printf("In process thread | new_socket = %d\n",*(con_obj->new_socket));
printf("j = %d | request_line = %s\n",(con_obj->request_line_size),(con_obj->request_line));
char *path=NULL;
char*request_type=NULL;
//path will be allocated and get null ['\0'] terminated in handle_process
printf("before handle_process\n");
int request_type_size=handle_process(con_obj,&path,&request_type);
if(request_type_size==0)
{
//different request_type
close(*(con_obj->new_socket));
if(path!=NULL)
free(path);
if(request_type!=NULL)
free(request_type);
free(con_obj);
return (void*)0;
}
printf("after handle_process\n" );
if(path!=NULL)
{
printf("in handle_process Path Len = %zu Request Path = '%s'\n",strlen(path),path);
}
if(request_type!=NULL)
{
printf("in handle_process Type Len = %zu Request Type = '%s'\n",strlen(request_type),request_type);
}
if(path!=NULL && request_type!=NULL)
{
if(strncmp(request_type,"GET",request_type_size)==0)
{
printf("inside GET in process func\n");
char *dirs;
char *file;
file=malloc(sizeof(char)*strlen(path));
// get_dirs_file: returns '/ ' for TYPE_MAIN | 'style9.css' for TYPE_CSS | 'title=&price=' for TYPE_QUERY
r= get_dirs_file(&path[0],file);//get null terminated string values
printf("\n\npath to follow -- = 'path = %s' 'file = %s'\n\n",path,file);
if(r == TYPE_MAIN)
{
respond_main(con_obj,RESPONSE_MAIN_HTML);
}
else if(r== TYPE_CSS)
{
respond_main(con_obj,RESPONSE_MAIN_CSS);
}
else if(r=TYPE_QUERY)
{
respond_main(con_obj,RESPONSE_MIAN_QUERY);
}
free(file);
}
}
close(*(con_obj->new_socket));
free(con_obj);
printf("------------------------------------------------------------------------------------\n");
}
else
{
printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
printf("No space for malloc on heap\n");
}
return (void *)0;
}
this is file.c
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "headers/accept.h"
#include <sys/types.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
int get_file_type(char *path,char *file)
{
int i=0;
printf("%zu \n",strlen(path));
while(i<strlen(path))
{
if(path[i]=='?')
{
//query string
int j=0;
strcpy(file,&path[i+1]);
file[strlen(path)]='\0';
return TYPE_QUERY;
}
if(strncmp(&path[i],"html9.html",strlen(path))==0)
{
strcpy(file,"/ ");
return TYPE_MAIN;
}
if(strncmp(&path[i],".css",4)==0)
{
int j=strlen(path);
while(j>0)
{
if(path[j]=='/')
{
strcpy(&file[0],&path[j]);
break;
}
j--;
}
// file[j]='\0';
return TYPE_CSS;
}
i++;
}
return 0;
}
/*<-whether found return 1; else 0;*/
int getfile_data(char *path,char *file)
{
int ret=get_file_type(path,file);
printf("request found !!! %s\n",file);
if(ret==TYPE_MAIN)
{
printf("responding with main page\n" );
return TYPE_MAIN;
}
else if(ret ==TYPE_CSS)
{
printf("responding with css\n");
return TYPE_CSS;
}
else if(ret ==TYPE_QUERY)
{
printf("finally saving data and redirecting user to main with message\n" );
return TYPE_QUERY;
}
else{
return 0;
}
//strncpy(**file,"fwd",4);
}
int get_dirs_file( char *path,char *file)
{
printf("in get_dirs_file");
int ret=getfile_data(path,file);
return ret;
}
this is listhell.c
//for fullfilling user requests
#include <stdio.h>
#include "headers/accept.h"
int respond_main(struct connection *con_obj,int response_type)
{
char *html_header = "HTTP/1.1 200 Okay\r\nContent-Type: text/html; charset=ISO-8859-4 \r\n\r\n";
char *css_header = "HTTP/1.1 200 Okay\r\nContent-Type: text/css\r\n\r\n";
char *data_saved_message="HTTP/1.1 200 Okay\r\nContent-Type: text/html; charset=ISO-8859-4 \r\n\r\n<html><body>add posted. will appear in 24 hours on listhell <a href=\"http://listhell.com/\">go to main page</a></body></html>";
if(response_type==RESPONSE_MAIN_HTML)
{
struct stat sb_html;
send(*(con_obj->new_socket) , html_header , strlen(html_header) , 0 );
sleep(10);
int fd_in_html=open("/home/user/Desktop/lh/html9.html",O_RDONLY);
const char* filename_html="/home/user/Desktop/lh/html9.html";
if(fd_in_html!=-1)
{
if (stat(filename_html, &sb_html) == -1)
{
printf("stat error %d\n",errno);
}
int x3=sendfile(*(con_obj->new_socket),fd_in_html,0,sb_html.st_size);
close(fd_in_html);
return HTTP_OK_200;
}
}
else if(response_type==RESPONSE_MAIN_CSS)
{
struct stat sb_css;
int fd_in_css=open("/home/user/Desktop/lh/css/style9.css",O_RDONLY);
if(fd_in_css!=-1)
{
const char* filename_css="/home/user/Desktop/lh/css/style9.css";
if (stat(filename_css, &sb_css) == -1)
{
printf("stat error %d\n",errno);
exit(EXIT_FAILURE);
}
sendfile(*(con_obj->new_socket),fd_in_css,0,sb_css.st_size);
close(fd_in_css);
return HTTP_OK_200;
}
}
else if(response_type==RESPONSE_MIAN_QUERY)
{
//
send(*(con_obj->new_socket) , data_saved_message , strlen(data_saved_message) , 0 );
//send(*(con_obj->new_socket) , data_saved_message , 200 , 0 );
//send(*(con_obj->new_socket) , data_saved_message , 200 , 0 );
//data_saved_message
printf("data saved\n");
return HTTP_OK_200;
}
return 0;
}
This is sendfile.c
#include <stdio.h>
#include "headers/accept.h"
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count)
{
off_t orig;
if (offset != NULL) {
/* Save current file offset and set offset to value in '*offset' */
orig = lseek(in_fd, 0, SEEK_CUR);
if (orig == -1)
return -1;
if (lseek(in_fd, *offset, SEEK_SET) == -1)
return -1;
}
size_t totSent = 0;
while (count > 0) {
size_t toRead = min(BUF_SIZE, count);
char buf[BUF_SIZE];
ssize_t numRead = read(in_fd, buf, toRead);
if (numRead == -1)
return -1;
if (numRead == 0)
break; /* EOF */
ssize_t numSent = write(out_fd, buf, numRead);
if (numSent == -1)
return -1;
if (numSent == 0) /* Should never happen */
printf("fatal: should never happen");
//fatal("sendfile: write() transferred 0 bytes");
count -= numSent;
totSent += numSent;
}
if (offset != NULL) {
/* Return updated file offset in '*offset', and reset the file offset
to the value it had when we were called. */
*offset = lseek(in_fd, 0, SEEK_CUR);
if (*offset == -1)
return -1;
if (lseek(in_fd, orig, SEEK_SET) == -1)
return -1;
}
return totSent;
}
accept.h
#ifndef SERVER
#define SERVER
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <pthread.h>
#include <malloc.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <netinet/tcp.h>
#include <time.h>
#define PORT 80
void accept1(int server_fd,struct sockaddr_in address,int addrlen);
struct connection
{
int *new_socket;
int type;
struct sockaddr_in address;
char *request_line;
int request_line_size;
int server_fd;
};
struct lh
{
int adid;
char title[250];
float price;
char city[75];
char state[125];
char country[125];
};
void *handle_request(void *arg);
void *process(void *p);
int handle_process(struct connection *con_obj,char **path,char **request_type);
int get_dirs_file( char *path,char *file);
int respond_main(struct connection *con_obj,int response_type);
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
//request type
#define TYPE_MAIN 2
#define TYPE_CSS 3
#define TYPE_QUERY 4
//reply type
#define RESPONSE_MAIN_HTML 2
#define RESPONSE_MAIN_CSS 3
#define RESPONSE_MIAN_QUERY 4
//
#define BUF_SIZE 20000
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
//HTTP RESPONSE
#define HTTP_OK_200 200
#endif
makefile
HEADERS = headers/
lh: accept.o server.o process.o file.o listhell.o
cc -g -pthread -o lh accept.o server.o process.o file.o listhell.o
listhell.o: $(HEADERS)accept.h listhell.c
cc -g -c -pthread listhell.c
process.o : $(HEADERS)accept.h process.c
cc -g -c -pthread process.c
file.o : $(HEADERS)accept.h file.c
cc -g -c -pthread file.c
server.o : $(HEADERS)accept.h server.c
cc -g -c -pthread server.c
accept.o : $(HEADERS)accept.h accept.c
cc -g -c -pthread accept.c
clean :
rm lh accept.o server.o process.o file.o listhell.o