-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.c
More file actions
executable file
·247 lines (204 loc) · 9.1 KB
/
server.c
File metadata and controls
executable file
·247 lines (204 loc) · 9.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
/*******************************/
/*
/* Project Name: Project 6: You Got Served
/* Description: Use socket programming to create a web server
/* File names: server.c, makefile
/* Date: Wednesday, April 29, 2015, 3:00pm
/* Due by: Friday, May 1, 2015 at 11:59pm
/* Author: Ryan Schubert
/*
/*******************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <ctype.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
char* getType(char* path);
void sendFile(char* path, char* hData, char* fBuffer, int c1, FILE* file, struct stat buf);
void fileNotFound(char* path, char* FNF);
int main( int argc, char** argv )
{
int i,j = 0;
if(argc != 3) //if there are not three arguments, print error and quit
{
printf("Usage: ./server <port> <path to root>\n");
return 0;
}
int port = atoi(argv[1]); //get the port
const char* dir = argv[2]; //get the directory
if(chdir(dir) == -1) //if we can't change to the directory, print error and quit
{
printf("Could not change to directory: %s\n", dir);
return 0;
}
int s1 = 0;
int c1 = 0;
int optval = 1;
char ip[15] = "127.0.0.1"; //local IP
struct sockaddr_in address;
struct sockaddr_storage otherAddress; //initialize socket structs
socklen_t otherSize = sizeof(otherAddress);
s1 = socket(AF_INET, SOCK_STREAM, 0); //get socket
setsockopt(s1, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); //make the socket reusable
memset(&address, 0, sizeof(address)); //bind the socket to the local IP and port
address.sin_family = AF_INET;
address.sin_port = htons(port);
address.sin_addr.s_addr = INADDR_ANY;
bind(s1, (struct sockaddr*)&address, sizeof(address));
listen(s1, 1); //listen
while(1) //contint accepting new connections
{
c1 = accept(s1, (struct sockaddr*) &otherAddress, &otherSize); //accept
printf("Got a client: \n");
char req[4];
char path[100];
char http[10];
char reqBuffer[200];
char fBuffer[1024];
struct stat buf;
for(i = 0 ; i < 99 ; ++i) //initialize path as spaces to get length
path[i] = ' ';
path[100] = '\0';
i = 0;
recv(c1, reqBuffer, 200, 0); //recieve the request from the connection
sscanf(reqBuffer, "%s %s %s", req, path, http); //read in the first three strings
while(path[i] != ' ') //get the length of path
++i;
int pLen = i;
i = 0;
int getOrHead = 0;
if(strncmp(req, "GET", 3) == 0)
getOrHead = 1;
else if(strncmp(req, "HEAD", 4) == 0)
getOrHead = 2;
if(getOrHead == 1 || getOrHead == 2 ) //if GET or HEAD request
{
if(path[pLen] == '/') //if the file path ends with a slash (/), concatenate index.html onto the path.
{
strcat(path, "index.html");
pLen += 10;
}
if(path[0] == '/') //if the file path starts with a slash (/), skip it.
for(i = 1 ; i < 100 ; ++i)
{
path[i-1] = path[i];
--pLen;
}
if(getOrHead == 1) //if it is a GET request
{
printf("\t GET %s\n", path);
FILE* file = fopen(path, "rb"); //open the file specified
if(file != NULL) //if the file exists
{
char hData[40];
sprintf(hData, "HTTP/1.0 200 OK\r\n"); //send the first line of header
send(c1, hData, strlen(hData), 0);
sendFile(path, hData, fBuffer, c1, file, buf); //send the rest of the header and the file
printf("Sent file: %s\n", path);
}
else //if the file is not found
{
char FNF[1251 + strlen(path)];
fileNotFound(path, FNF); //get the code for the 404 page
char hData[40];
sprintf(hData, "HTTP/1.0 404 Not Found\r\n"); //send header data
send(c1, hData, strlen(hData), 0);
sprintf(hData, "Content-Type: %s\r\n", "html");
send(c1, hData, strlen(hData), 0);
sprintf(hData, "Content-Length: %d\r\n\r\n", ((int)strlen(FNF)+1));
send(c1, hData, strlen(hData), 0);
send(c1, FNF, strlen(FNF), 0); //send 404 page
printf("File not found: %s\n", path);
}
}
else
{
char hData[40];
sprintf(hData, "HTTP/1.0 200 OK\r\n"); //send the first line of header
send(c1, hData, strlen(hData), 0);
stat(path, &buf);
int size1 = buf.st_size; //gets the size of the file
sprintf(hData, "Content-Length: %d\r\n", size1); //sends header data
send(c1, hData, strlen(hData), 0);
sprintf(hData, "Content-Type: %s\r\n", getType(path));
send(c1, hData, strlen(hData), 0);
printf("Sent head: %s\n", path);
}
}
}
}
/*
* var: char* path, hData, fBuffer
* var: int c1
* var: FILE* file
* var: struct stat buf
* sends the rest of the header data and file
*/
void sendFile(char* path, char* hData, char* fBuffer, int c1, FILE* file, struct stat buf)
{
stat(path, &buf);
int size1 = buf.st_size; //gets the size of the file
sprintf(hData, "Content-Type: %s\r\n", getType(path)); //sends header data
send(c1, hData, strlen(hData), 0);
sprintf(hData, "Content-Length: %d\r\n\r\n", size1);
send(c1, hData, strlen(hData), 0);
int readIn = 0;
while((readIn = fread(fBuffer, sizeof(char), 1024, file)) != 0) //sends the rest of the file
send(c1, fBuffer, readIn, 0);
}
/*
* var: char* path
* return: char*
* returns the file type
*/
char* getType(char* path)
{
char temp[20];
int i, j, len;
len = strlen(path); //length of path
for(i = len ; path[i-1] != '.' ; --i); //index of the file extension
for(j = 0 ; i < len ; j++)
{
temp[j] = path[i]; //gets file extension
i++;
}
if(strcmp(temp, "html") == 0) //returns the correct file type based on the extension
return "text/html";
else if(strcmp(temp, "htm") == 0)
return "text/html";
else if(strcmp(temp, "jpg") == 0)
return "image/jpeg";
else if(strcmp(temp, "jpeg") == 0)
return "image/jpeg";
else if(strcmp(temp, "gif") == 0)
return "image/gif";
else if(strcmp(temp, "png") == 0)
return "image/png";
else if(strcmp(temp, "txt") == 0)
return "text/plain";
else if(strcmp(temp, "c") == 0)
return "text/plain";
else if(strcmp(temp, "h") == 0)
return "text/plain";
else if(strcmp(temp, "pdf") == 0)
return "application/pdf";
else
return "application/unknown"; //returns unknown if it isn't supported
}
/*
* var: char* path, FNF
* concatenates the html code for the 404 page into a string, including the file that was not found
*/
void fileNotFound(char* path, char* FNF)
{
sprintf(FNF, "<!--A Design by W3layouts Author: W3layout Author URL: http://w3layouts.com License: Creative Commons Attribution 3.0 Unported License URL: http://creativecommons.org/licenses/by/3.0/ --> <!DOCTYPE HTML> <html> <head> <title>Free 404 for Website Template | Home :: w3layouts</title> <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/> <link href=\"http://fonts.googleapis.com/css?family=Fjalla+One\" rel=\"stylesheet\" type=\"text/css\"> <style type=\"text/css\"> body{ background-color: #4DB3B3 ; } .wrap{ margin:0 auto; width:1000px; } .title{ margin-bottom: 40px; } .title h1{ font-size:100px; color: #E64A45; text-align:center; margin-top:100px; text-shadow:6px 1px 6px #333; font-family: 'Fjalla One', sans-serif; } .title h2{ font-size:100px; color: #E64A45; text-align:center; margin-bottom:1px; text-shadow:6px 1px 6px #333; font-family: 'Fjalla One', sans-serif; margin-top: -20px; } .title h3{ font-size:45px; color: #E64A45; text-align:center; margin-bottom:1px; text-shadow:6px 1px 6px #333; font-family: 'Fjalla One', sans-serif; margin-top: 75px; } </style> </head> <body> <div class=\"wrap\"> <div class=\"title\"> <h1>You've Failed.</h1> <h2>404 Error!</h2> <h3>\"%s\" does not exist!</h3> </div> </div> </div> </body>", path);
}