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
Show 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 @@
...
@@ -2,6 +2,7 @@
*.out
*.out
*.o
*.o
*.html
*.html
*.tgz
!public/*.html
!public/*.html
http/client
http/client
http/server
http/server
http/Makefile
View file @
36495526
...
@@ -25,3 +25,7 @@ clean:
...
@@ -25,3 +25,7 @@ clean:
$(RM)
$(TARGET_2)
$(RM)
$(TARGET_2)
$(RM)
*
.o
$(RM)
*
.o
$(RM)
*
.html
$(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 @@
...
@@ -14,10 +14,8 @@
#define LISTEN_BACKLOG 5 //< Define maximum size of the input queue
#define LISTEN_BACKLOG 5 //< Define maximum size of the input queue
static
int
create_server_socket
(
uint16_t
port
,
struct
sockaddr_in
incoming
);
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
*
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
[])
{
int
main
(
int
argc
,
char
*
argv
[])
{
check_opts_number
(
argc
);
check_opts_number
(
argc
);
...
@@ -67,14 +65,31 @@ int main(int argc, char *argv[]) {
...
@@ -67,14 +65,31 @@ int main(int argc, char *argv[]) {
incoming
.
sin_family
=
AF_INET
;
//< Use IPv4
incoming
.
sin_family
=
AF_INET
;
//< Use IPv4
int
sockfd
=
create_server_socket
(
port
,
incoming
);
//< Define a server socket
int
sockfd
=
create_server_socket
(
port
,
incoming
);
//< Define a server socket
int
current_session
=
0
;
socklen_t
peer_addr_size
=
sizeof
(
struct
sockaddr_in
);
socklen_t
peer_addr_size
=
sizeof
(
struct
sockaddr_in
);
while
(
1
)
{
//< Accept connections until terminated
/// Start accepting connections
/// Start accepting connections
int
current_session
=
accept
(
sockfd
,
(
struct
sockaddr
*
)
&
incoming
,
&
peer_addr_size
);
//< Save the current session
current_session
=
accept
(
sockfd
,
(
struct
sockaddr
*
)
&
incoming
,
&
peer_addr_size
);
//< Save the current session
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__
);
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
/// Setup the server response
response
=
setup_server_response
(
dir
,
ifile
,
current_session
,
sockfd
);
response
=
setup_server_response
(
dir
,
ifile
,
request
);
/// Send the response to the client
/// Send the response to the client
if
(
send
(
current_session
,
response
,
strlen
(
response
)
+
1
,
0
)
<
0
)
{
if
(
send
(
current_session
,
response
,
strlen
(
response
)
+
1
,
0
)
<
0
)
{
...
@@ -83,6 +98,8 @@ int main(int argc, char *argv[]) {
...
@@ -83,6 +98,8 @@ int main(int argc, char *argv[]) {
close
(
sockfd
);
close
(
sockfd
);
exit
(
EXIT_FAILURE
);
exit
(
EXIT_FAILURE
);
}
}
}
}
close
(
current_session
);
close
(
current_session
);
close
(
sockfd
);
close
(
sockfd
);
...
@@ -153,80 +170,80 @@ static int create_server_socket(uint16_t port, struct sockaddr_in incoming) {
...
@@ -153,80 +170,80 @@ static int create_server_socket(uint16_t port, struct sockaddr_in incoming) {
/**
/**
* @brief Function to create the HTTP response
* @brief Function to create the HTTP response
* @details Gets the client request
* @details Gets the client request
* If there is no current session, 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 the server could not receive a client connection, it exits with an error
* If a GET request is received, the function tries to open the resource:
* 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 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 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)
* At the end, it returns the server response with header and body (if available)
* @param dir - the directory of the file
* @param dir - the directory of the file
* filename - the name of the file
* ifile - the name of the indexfile
* current_session - the current client session
* request - the request of the client
* sockfd - the socket configuration
* @return response - A header with the status code and a body (if available)
* @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
)
{
static
char
*
setup_server_response
(
char
*
dir
,
char
*
ifile
,
char
*
request
)
{
if
(
current_session
<
0
)
{
char
*
response
=
malloc
(
sizeof
(
char
)
*
__INT16_MAX__
);
(
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__
];
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
];
char
method
[
4
];
strncpy
(
method
,
request
,
4
);
//< Get the request type
strncpy
(
method
,
request
,
3
);
//< Get the request type
method
[
3
]
=
0
;
//< Add terminating char
method
[
3
]
=
0
;
//< Add terminating string
char
header
[
__INT8_MAX__
+
100
];
char
header
[
__INT8_MAX__
+
100
];
if
(
strcmp
(
method
,
"GET"
)
==
0
)
{
if
(
strcmp
(
method
,
"GET"
)
==
0
)
{
char
*
body
=
get_file_contents
(
dir
,
filename
);
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
,
"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
);
}
}
if
(
body
!=
NULL
)
{
if
(
body
!=
NULL
)
{
time_t
t
=
time
(
NULL
);
time_t
current_time
;
struct
tm
tm
=
*
gmtime
(
&
t
);
time
(
&
current_time
);
struct
tm
*
tm
=
gmtime
(
&
current_time
);
char
time_string
[
50
];
char
*
wday
=
wday_to_string
(
tm
.
tm_wday
);
strftime
(
time_string
,
50
,
"%a, %d %b %y %H:%M:%S %Z"
,
tm
);
char
*
month
=
month_to_string
(
tm
.
tm_mon
+
1
);
snprintf
(
snprintf
(
header
,
header
,
sizeof
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
"
,
"HTTP/1.1 200 OK
\r\n
Date:
%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
)
time_string
,
strlen
(
body
)
);
//< Build the 200 header
);
//< Build the 200 header
strcat
(
response
,
header
);
strcat
(
response
,
header
);
strcat
(
response
,
body
);
strcat
(
response
,
body
);
}
else
{
}
else
{
snprintf
(
strcpy
(
header
,
header
,
sizeof
header
,
"HTTP/1.1 404 Not Found
\r\n
Connection: close
\r\n\r\n
"
"HTTP/1.1 404 Not Found
\r\n
Connection: close
\r\n\r\n
"
);
//< Build the 404 header
);
//< Build the 404 header
strcat
(
response
,
header
);
strcat
(
response
,
header
);
}
}
}
else
{
}
else
{
fprintf
(
stderr
,
"ERROR: Unhandled HTTP request method received
\n
"
);
strcpy
(
snprintf
(
header
,
header
,
sizeof
header
,
"HTTP/1.1 501 Not Implemented
\r\n
Connection: close
\r\n\r\n
"
"HTTP/1.1 501 Not ImplementedConnection: close
\r\n\r\n
"
);
//< Build 501 the header
);
//< Build 501 the header
strcat
(
response
,
header
);
strcat
(
response
,
header
);
}
}
return
response
;
return
response
;
}
}
}
}
/**
/**
...
@@ -256,77 +273,8 @@ static char * get_file_contents(char *dir, char *filename) {
...
@@ -256,77 +273,8 @@ static char * get_file_contents(char *dir, char *filename) {
int
file_length
=
ftell
(
file
);
//< Get file length
int
file_length
=
ftell
(
file
);
//< Get file length
fseek
(
file
,
0
,
SEEK_SET
);
//< Set the position to begining of stream
fseek
(
file
,
0
,
SEEK_SET
);
//< Set the position to begining of stream
res
=
malloc
(
file_length
);
//< Allocate memory for the file contents
res
=
malloc
(
file_length
);
//< Allocate memory for the file contents
if
(
res
!=
0
)
{
fread
(
res
,
1
,
file_length
,
file
);
//< Read the contents into res
fread
(
res
,
1
,
file_length
,
file
);
//< Read the contents into res
}
else
{
return
" "
;
}
return
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