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
a8698e38
Commit
a8698e38
authored
Nov 09, 2018
by
Ivaylo Ivanov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add functioning server
parent
400c3916
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
177 additions
and
44 deletions
+177
-44
http/client.c
http/client.c
+1
-1
http/public/greetings.html
http/public/greetings.html
+12
-0
http/public/index.html
http/public/index.html
+12
-0
http/server.c
http/server.c
+152
-43
No files found.
http/client.c
View file @
a8698e38
...
...
@@ -105,7 +105,7 @@ int main(int argc, char *argv[]) {
exit
(
EXIT_FAILURE
);
}
char
reply
[
sizeof
(
int32_t
)
];
//< Set the variable to hold the server response. Set to a big length
char
reply
[
__INT16_MAX__
];
//< Set the variable to hold the server response. Set to a big length
if
((
recv
(
sockfd
,
reply
,
strlen
(
reply
)
-
1
,
0
))
<
0
)
{
//< Receive response from the remote (-1 for the trailing terminating char)
(
void
)
fprintf
(
stderr
,
"ERROR: Did not receive response from the remote.
\n
"
);
...
...
http/public/greetings.html
View file @
a8698e38
<!DOCTYPE html>
<html>
<head>
<meta
charset=
"utf-8"
/>
<meta
http-equiv=
"X-UA-Compatible"
content=
"IE=edge"
>
<title>
Greetings
</title>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1"
>
</head>
<body>
<h1>
Hello, World!
</h1>
</body>
</html>
\ No newline at end of file
http/public/index.html
View file @
a8698e38
<!DOCTYPE html>
<html>
<head>
<meta
charset=
"utf-8"
/>
<meta
http-equiv=
"X-UA-Compatible"
content=
"IE=edge"
>
<title>
Index
</title>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1"
>
</head>
<body>
<h1>
This is the index page
</h1>
</body>
</html>
\ No newline at end of file
http/server.c
View file @
a8698e38
...
...
@@ -14,7 +14,10 @@
#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
*
get_file_contents
(
char
*
dir
,
char
*
file
);
static
char
*
setup_server_response
(
char
*
dir
,
char
*
filename
,
int
current_session
,
int
sockfd
);
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
);
...
...
@@ -22,7 +25,7 @@ int main(int argc, char *argv[]) {
char
*
cport
=
"8080"
;
char
*
ifile
=
"index.html"
;
char
*
dir
=
NULL
;
char
response
[
sizeof
(
int32_t
)]
;
//< To hold the server response
char
*
response
;
//< To hold the server response
int
c
;
/// Process the options
...
...
@@ -70,46 +73,8 @@ int main(int argc, char *argv[]) {
/// Start accepting connections
int
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
(
sockfd
);
exit
(
EXIT_FAILURE
);
}
else
{
char
request
[
sizeof
(
int32_t
)];
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
if
(
strcmp
(
method
,
"GET"
)
==
0
)
{
(
void
)
fprintf
(
stdout
,
"Got here
\n
"
);
close
(
current_session
);
close
(
sockfd
);
}
else
{
fprintf
(
stderr
,
"ERROR: Unhandled HTTP request method received
\n
"
);
char
header
[
sizeof
(
int8_t
)
+
100
];
time_t
t
=
time
(
NULL
);
struct
tm
tm
=
*
localtime
(
&
t
);
snprintf
(
header
,
sizeof
header
,
"HTTP/1.1 501 Not Implemented
\r\n
Date: %d, %d %d %d %d:%d:%d %s
\r\n
Content-Length: 0
\r\n
Connection: close
\r\n\r\n
"
,
tm
.
tm_wday
,
tm
.
tm_mday
,
tm
.
tm_mon
,
tm
.
tm_year
+
1900
,
tm
.
tm_hour
,
tm
.
tm_min
,
tm
.
tm_sec
,
tm
.
tm_zone
);
//< Build the header
puts
(
header
);
strncpy
(
response
,
header
,
sizeof
(
header
));
}
close
(
current_session
);
close
(
sockfd
);
}
}
/// Setup the server response
response
=
setup_server_response
(
dir
,
ifile
,
current_session
,
sockfd
);
/// Send the response to the client
if
(
send
(
current_session
,
response
,
strlen
(
response
)
+
1
,
0
)
<
0
)
{
...
...
@@ -185,6 +150,85 @@ static int create_server_socket(uint16_t port, struct sockaddr_in incoming) {
return
sockfd
;
}
/**
* @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 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
* 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
* @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__
];
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
(
header
,
sizeof
header
,
"HTTP/1.1 501 Not ImplementedConnection: close
\r\n\r\n
"
);
//< Build 501 the header
strcat
(
response
,
header
);
}
return
response
;
}
}
}
/**
* @brief Function to take the contents of a specified file
* @details Gets the contents of the file specified
...
...
@@ -196,7 +240,8 @@ static int create_server_socket(uint16_t port, struct sockaddr_in incoming) {
* @return res - The contents of the file, formatted as a string
**/
static
char
*
get_file_contents
(
char
*
dir
,
char
*
filename
)
{
char
*
path
=
strcpy
(
dir
,
filename
);
char
path
[
strlen
(
dir
)
+
strlen
(
filename
)
+
100
];
//< set the variable for the path with a reasonable length
snprintf
(
path
,
sizeof
path
,
"%s%s"
,
dir
,
filename
);
FILE
*
file
=
NULL
;
...
...
@@ -221,3 +266,67 @@ static char * get_file_contents(char *dir, char *filename) {
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