Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
unix
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
tu-wien
unix
Commits
36495526
Commit
36495526
authored
Nov 10, 2018
by
Ivaylo Ivanov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make the server listen constantly and fix a bug
parent
a8698e38
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
97 additions
and
144 deletions
+97
-144
.gitignore
.gitignore
+1
-0
http/Makefile
http/Makefile
+5
-1
http/server.c
http/server.c
+91
-143
No files found.
.gitignore
View file @
36495526
...
...
@@ -2,6 +2,7 @@
*.out
*.o
*.html
*.tgz
!public/*.html
http/client
http/server
http/Makefile
View file @
36495526
...
...
@@ -24,4 +24,8 @@ clean:
$(RM)
$(TARGET_1)
$(RM)
$(TARGET_2)
$(RM)
*
.o
$(RM)
*
.html
\ No newline at end of file
$(RM)
*
.html
$(RM)
*
.tgz
package
:
tar
-cvzf
server.tgz
$(TARGET_1)
.c
$(TARGET_2)
.c shared public Makefile
http/server.c
View file @
36495526
...
...
@@ -14,10 +14,8 @@
#define LISTEN_BACKLOG 5 //< Define maximum size of the input queue
static
int
create_server_socket
(
uint16_t
port
,
struct
sockaddr_in
incoming
);
static
char
*
setup_server_response
(
char
*
dir
,
char
*
filename
,
int
current_session
,
int
sockfd
);
static
char
*
setup_server_response
(
char
*
dir
,
char
*
ifile
,
char
*
request
);
static
char
*
get_file_contents
(
char
*
dir
,
char
*
filename
);
static
char
*
wday_to_string
(
int
day
);
static
char
*
month_to_string
(
int
month
);
int
main
(
int
argc
,
char
*
argv
[])
{
check_opts_number
(
argc
);
...
...
@@ -67,21 +65,40 @@ int main(int argc, char *argv[]) {
incoming
.
sin_family
=
AF_INET
;
//< Use IPv4
int
sockfd
=
create_server_socket
(
port
,
incoming
);
//< Define a server socket
int
current_session
=
0
;
socklen_t
peer_addr_size
=
sizeof
(
struct
sockaddr_in
);
/// Start accepting connections
int
current_session
=
accept
(
sockfd
,
(
struct
sockaddr
*
)
&
incoming
,
&
peer_addr_size
);
//< Save the current session
while
(
1
)
{
//< Accept connections until terminated
/// Start accepting connections
current_session
=
accept
(
sockfd
,
(
struct
sockaddr
*
)
&
incoming
,
&
peer_addr_size
);
//< Save the current session
/// Setup the server response
response
=
setup_server_response
(
dir
,
ifile
,
current_session
,
sockfd
);
if
(
current_session
<
0
)
{
(
void
)
fprintf
(
stderr
,
"ERROR: Could not start accepting connections
\n
"
);
close
(
current_session
);
close
(
sockfd
);
exit
(
EXIT_FAILURE
);
}
else
{
char
*
request
=
malloc
(
sizeof
(
char
)
*
__INT16_MAX__
);
/// Send the response to the client
if
(
send
(
current_session
,
response
,
strlen
(
response
)
+
1
,
0
)
<
0
)
{
(
void
)
fprintf
(
stderr
,
"ERROR: Could not send the response to the client
\n
"
);
close
(
current_session
);
close
(
sockfd
);
exit
(
EXIT_FAILURE
);
if
(
recv
(
current_session
,
request
,
strlen
(
request
)
-
1
,
0
)
<
0
)
{
(
void
)
fprintf
(
stderr
,
"ERROR: Could not receive connection from client
\n
"
);
close
(
current_session
);
close
(
sockfd
);
exit
(
EXIT_FAILURE
);
}
/// Setup the server response
response
=
setup_server_response
(
dir
,
ifile
,
request
);
/// Send the response to the client
if
(
send
(
current_session
,
response
,
strlen
(
response
)
+
1
,
0
)
<
0
)
{
(
void
)
fprintf
(
stderr
,
"ERROR: Could not send the response to the client
\n
"
);
close
(
current_session
);
close
(
sockfd
);
exit
(
EXIT_FAILURE
);
}
}
}
close
(
current_session
);
...
...
@@ -153,80 +170,80 @@ static int create_server_socket(uint16_t port, struct sockaddr_in incoming) {
/**
* @brief Function to create the HTTP response
* @details Gets the client request
* If there is no current session, it exits with an error
* If the server could not receive a client connection, it exits with an error
* If the server receives an invalid requests, a 400 header is build and the function adds it to response
* If a GET request is received, the function tries to open the resource:
* - if it could open it, it builds a 200 header and the file contents as body and adds them to response
* - if it could not open it, it builds a 404 header and adds it to response
* If anything other than a GET request is received, a 501 header is build
, adds it to response and logs it
* If anything other than a GET request is received, a 501 header is build
and the function adds it to response
* At the end, it returns the server response with header and body (if available)
* @param dir - the directory of the file
* filename - the name of the file
* current_session - the current client session
* sockfd - the socket configuration
* ifile - the name of the indexfile
* request - the request of the client
* @return response - A header with the status code and a body (if available)
**/
static
char
*
setup_server_response
(
char
*
dir
,
char
*
filename
,
int
current_session
,
int
sockfd
)
{
if
(
current_session
<
0
)
{
(
void
)
fprintf
(
stderr
,
"ERROR: Could not start accepting connections
\n
"
);
close
(
current_session
);
close
(
sockfd
);
exit
(
EXIT_FAILURE
);
}
else
{
char
request
[
__INT16_MAX__
];
static
char
response
[
__INT16_MAX__
];
static
char
*
setup_server_response
(
char
*
dir
,
char
*
ifile
,
char
*
request
)
{
char
*
response
=
malloc
(
sizeof
(
char
)
*
__INT16_MAX__
);
if
(
recv
(
current_session
,
request
,
strlen
(
request
)
-
1
,
0
)
<
0
)
{
(
void
)
fprintf
(
stderr
,
"ERROR: Could not receive connection from client
\n
"
);
close
(
current_session
);
close
(
sockfd
);
exit
(
EXIT_FAILURE
);
}
else
{
char
method
[
4
];
strncpy
(
method
,
request
,
4
);
//< Get the request type
method
[
3
]
=
0
;
//< Add terminating char
char
header
[
__INT8_MAX__
+
100
];
if
(
strcmp
(
method
,
"GET"
)
==
0
)
{
char
*
body
=
get_file_contents
(
dir
,
filename
);
if
(
body
!=
NULL
)
{
time_t
t
=
time
(
NULL
);
struct
tm
tm
=
*
gmtime
(
&
t
);
char
*
wday
=
wday_to_string
(
tm
.
tm_wday
);
char
*
month
=
month_to_string
(
tm
.
tm_mon
+
1
);
snprintf
(
header
,
sizeof
header
,
"HTTP/1.1 200 OK
\r\n
Date: %s, %d %s %d %d:%d:%d %s
\r\n
Content-Length: %ld
\r\n
Connection: close
\r\n\r\n
"
,
wday
,
tm
.
tm_mday
,
month
,
tm
.
tm_year
+
1900
,
tm
.
tm_hour
,
tm
.
tm_min
,
tm
.
tm_sec
,
tm
.
tm_zone
,
strlen
(
body
)
);
//< Build the 200 header
strcat
(
response
,
header
);
strcat
(
response
,
body
);
}
else
{
snprintf
(
header
,
sizeof
header
,
"HTTP/1.1 404 Not Found
\r\n
Connection: close
\r\n\r\n
"
);
//< Build the 404 header
strcat
(
response
,
header
);
}
}
else
{
fprintf
(
stderr
,
"ERROR: Unhandled HTTP request method received
\n
"
);
snprintf
(
char
method
[
4
];
strncpy
(
method
,
request
,
3
);
//< Get the request type
method
[
3
]
=
0
;
//< Add terminating string
char
header
[
__INT8_MAX__
+
100
];
if
(
strcmp
(
method
,
"GET"
)
==
0
)
{
char
*
body
=
NULL
;
char
*
delim
=
strstr
(
request
,
"/"
);
char
*
req_file
=
strtok
(
delim
,
" "
);
//< Get the requested file
if
(
strlen
(
req_file
)
==
1
)
{
body
=
get_file_contents
(
dir
,
ifile
);
}
else
{
char
*
rest
=
strstr
(
request
,
"HTTP/1.1"
);
rest
=
strtok
(
rest
,
"
\r\n
"
);
if
(
rest
==
NULL
)
{
strcpy
(
header
,
sizeof
header
,
"HTTP/1.1 501 Not ImplementedConnection: close
\r\n\r\n
"
);
//< Build 501 the header
"HTTP/1.1 400 Bad Request
\r\n
Connection: close
\r\n\r\n
"
);
//< Build the 400 header
strcat
(
response
,
header
);
}
else
{
body
=
get_file_contents
(
dir
,
req_file
+
1
);
(
void
)
fprintf
(
stdout
,
"GET: %s
\n
"
,
req_file
);
}
}
return
response
;
if
(
body
!=
NULL
)
{
time_t
current_time
;
time
(
&
current_time
);
struct
tm
*
tm
=
gmtime
(
&
current_time
);
char
time_string
[
50
];
strftime
(
time_string
,
50
,
"%a, %d %b %y %H:%M:%S %Z"
,
tm
);
snprintf
(
header
,
sizeof
header
,
"HTTP/1.1 200 OK
\r\n
Date: %s
\r\n
Content-Length: %ld
\r\n
Connection: close
\r\n\r\n
"
,
time_string
,
strlen
(
body
)
);
//< Build the 200 header
strcat
(
response
,
header
);
strcat
(
response
,
body
);
}
else
{
strcpy
(
header
,
"HTTP/1.1 404 Not Found
\r\n
Connection: close
\r\n\r\n
"
);
//< Build the 404 header
strcat
(
response
,
header
);
}
}
else
{
strcpy
(
header
,
"HTTP/1.1 501 Not Implemented
\r\n
Connection: close
\r\n\r\n
"
);
//< Build 501 the header
strcat
(
response
,
header
);
}
return
response
;
}
/**
...
...
@@ -256,77 +273,8 @@ static char * get_file_contents(char *dir, char *filename) {
int
file_length
=
ftell
(
file
);
//< Get file length
fseek
(
file
,
0
,
SEEK_SET
);
//< Set the position to begining of stream
res
=
malloc
(
file_length
);
//< Allocate memory for the file contents
if
(
res
!=
0
)
{
fread
(
res
,
1
,
file_length
,
file
);
//< Read the contents into res
}
else
{
return
" "
;
}
fread
(
res
,
1
,
file_length
,
file
);
//< Read the contents into res
return
res
;
}
}
/**
* @brief Function to convert a int weekday to string weekday
* @details Gets the weekday as int, converts it to string and returns the string
* @param day - the weekday as int
* @return the weekday as a string
**/
static
char
*
wday_to_string
(
int
day
)
{
switch
(
day
)
{
case
1
:
return
"Mon"
;
case
2
:
return
"Tue"
;
case
3
:
return
"Wed"
;
case
4
:
return
"Thu"
;
case
5
:
return
"Fri"
;
case
6
:
return
"Sat"
;
case
7
:
return
"Sun"
;
default:
return
NULL
;
}
}
/**
* @brief Function to convert a int month to string month
* @details Gets the month as int, converts it to string and returns the string
* @param day - the month as int
* @return the month as a string
**/
static
char
*
month_to_string
(
int
month
)
{
switch
(
month
)
{
case
1
:
return
"Jan"
;
case
2
:
return
"Feb"
;
case
3
:
return
"Mar"
;
case
4
:
return
"Apr"
;
case
5
:
return
"May"
;
case
6
:
return
"Jun"
;
case
7
:
return
"Jul"
;
case
8
:
return
"Aug"
;
case
9
:
return
"Sep"
;
case
10
:
return
"Oct"
;
case
11
:
return
"Nov"
;
case
12
:
return
"Dec"
;
default:
return
NULL
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment