Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
M
mongoose
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
esp
mongoose
Commits
d1bd1529
Commit
d1bd1529
authored
Nov 30, 2013
by
Sergey Lyubka
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
request pipelining done
parent
d00b7f43
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
102 additions
and
47 deletions
+102
-47
core.c
build/src/core.c
+102
-47
No files found.
build/src/core.c
View file @
d1bd1529
...
...
@@ -66,6 +66,9 @@ typedef __int64 int64_t;
#ifndef va_copy
#define va_copy(x,y) x = y
#endif // MINGW #defines va_copy
#ifndef __func__
#define __func__ ""
#endif
#else
#include <inttypes.h>
#include <unistd.h>
...
...
@@ -98,7 +101,7 @@ struct linked_list_link { struct linked_list_link *prev, *next; };
#define MAX_REQUEST_SIZE 16384
#define IOBUF_SIZE 8192
#define MAX_PATH_SIZE 8192
#define DBG(x) do { printf("%s:
%d: ", __FILE__, __LINE
__); \
#define DBG(x) do { printf("%s:
:%s() ", __FILE__, __func
__); \
printf x; putchar('\n'); fflush(stdout); } while(0)
//#define DBG(x)
...
...
@@ -131,6 +134,7 @@ struct mg_server {
char
*
config_options
[
NUM_OPTIONS
];
mg_event_handler_t
event_handler
;
void
*
user_data
;
sock_t
ctl
[
2
];
// Control socketpair. Used to wake up from select() call
};
struct
iobuf
{
...
...
@@ -534,13 +538,13 @@ static int is_valid_http_method(const char *method) {
// This function modifies the buffer by NUL-terminating
// HTTP request components, header names and header values.
static
int
parse_http_message
(
char
*
buf
,
int
len
,
struct
mg_request_info
*
ri
)
{
int
is_request
,
request_len
gth
=
get_request_len
((
unsigned
char
*
)
buf
,
len
);
if
(
request_len
gth
>
0
)
{
int
is_request
,
request_len
=
get_request_len
((
unsigned
char
*
)
buf
,
len
);
if
(
request_len
>
0
)
{
// Reset attributes. DO NOT TOUCH is_ssl, remote_ip, remote_port
ri
->
remote_user
=
ri
->
request_method
=
ri
->
uri
=
ri
->
http_version
=
NULL
;
ri
->
num_headers
=
0
;
buf
[
request_len
gth
-
1
]
=
'\0'
;
buf
[
request_len
-
1
]
=
'\0'
;
// RFC says that all initial whitespaces should be ingored
while
(
*
buf
!=
'\0'
&&
isspace
(
*
(
unsigned
char
*
)
buf
))
{
...
...
@@ -555,7 +559,7 @@ static int parse_http_message(char *buf, int len, struct mg_request_info *ri) {
is_request
=
is_valid_http_method
(
ri
->
request_method
);
if
((
is_request
&&
memcmp
(
ri
->
http_version
,
"HTTP/"
,
5
)
!=
0
)
||
(
!
is_request
&&
memcmp
(
ri
->
request_method
,
"HTTP/"
,
5
)
!=
0
))
{
request_len
gth
=
-
1
;
request_len
=
-
1
;
}
else
{
if
(
is_request
)
{
ri
->
http_version
+=
5
;
...
...
@@ -563,7 +567,7 @@ static int parse_http_message(char *buf, int len, struct mg_request_info *ri) {
parse_http_headers
(
&
buf
,
ri
);
}
}
return
request_len
gth
;
return
request_len
;
}
static
int
parse_range_header
(
const
char
*
header
,
int64_t
*
a
,
int64_t
*
b
)
{
...
...
@@ -658,6 +662,21 @@ int mg_url_decode(const char *src, int src_len, char *dst,
return
i
>=
src_len
?
j
:
-
1
;
}
// Return HTTP header value, or NULL if not found.
static
const
char
*
get_header
(
const
struct
mg_request_info
*
ri
,
const
char
*
s
)
{
int
i
;
for
(
i
=
0
;
i
<
ri
->
num_headers
;
i
++
)
if
(
!
strcmp
(
s
,
ri
->
http_headers
[
i
].
name
))
return
ri
->
http_headers
[
i
].
value
;
return
NULL
;
}
const
char
*
mg_get_header
(
const
struct
mg_connection
*
conn
,
const
char
*
name
)
{
return
get_header
(
&
conn
->
request_info
,
name
);
}
// Return 1 if real file has been found, 0 otherwise
static
int
convert_uri_to_file_name
(
struct
mg_connection
*
conn
,
char
*
buf
,
size_t
buf_len
,
struct
stat
*
st
)
{
...
...
@@ -721,7 +740,6 @@ static int vspool(struct iobuf *io, const char *fmt, va_list ap) {
va_copy
(
ap_copy
,
ap
);
len
=
vsnprintf
(
NULL
,
0
,
fmt
,
ap_copy
);
DBG
((
"len = %d"
,
len
));
if
(
len
<=
0
)
{
}
else
if
(
len
<
io
->
size
-
io
->
len
||
...
...
@@ -753,7 +771,7 @@ static void write_to_client(struct mg_connection *conn) {
struct
iobuf
*
io
=
&
conn
->
remote_iobuf
;
int
n
=
send
(
conn
->
client_sock
,
io
->
buf
,
io
->
len
,
0
);
DBG
((
"Written %d of %d(%d): [%.*s]"
,
n
,
io
->
len
,
io
->
size
,
0
,
io
->
buf
));
//
DBG(("Written %d of %d(%d): [%.*s]", n, io->len, io->size, 0, io->buf));
if
(
is_error
(
n
))
{
conn
->
flags
|=
CONN_CLOSE
;
...
...
@@ -791,6 +809,29 @@ static void open_local_endpoint(struct mg_connection *conn) {
}
}
static
int
io_space
(
const
struct
iobuf
*
io
)
{
return
io
->
size
-
io
->
len
;
}
static
void
process_request
(
struct
mg_connection
*
conn
)
{
struct
iobuf
*
io
=
&
conn
->
local_iobuf
;
DBG
((
"parse_http_message(%d [%.*s])"
,
io
->
len
,
io
->
len
,
io
->
buf
));
if
(
conn
->
request_len
==
0
)
{
conn
->
request_len
=
parse_http_message
(
io
->
buf
,
io
->
len
,
&
conn
->
request_info
);
}
DBG
((
"parse_http_message() -> %d"
,
conn
->
request_len
));
if
(
conn
->
request_len
<
0
||
(
conn
->
request_len
==
0
&&
io_space
(
io
)
<=
0
))
{
// Invalid request, or request is too big: close the connection
conn
->
flags
|=
CONN_CLOSE
;
}
else
if
(
conn
->
request_len
>
0
&&
conn
->
endpoint_type
==
EP_NONE
)
{
open_local_endpoint
(
conn
);
}
}
static
void
read_from_client
(
struct
mg_connection
*
conn
)
{
struct
iobuf
*
io
=
&
conn
->
local_iobuf
;
int
n
=
recv
(
conn
->
client_sock
,
io
->
buf
+
io
->
len
,
io
->
size
-
io
->
len
,
0
);
...
...
@@ -803,76 +844,90 @@ static void read_from_client(struct mg_connection *conn) {
conn
->
flags
|=
CONN_CLOSE
;
}
else
if
(
n
>
0
)
{
io
->
len
+=
n
;
if
(
conn
->
request_len
==
0
)
{
conn
->
request_len
=
parse_http_message
(
io
->
buf
,
io
->
len
,
&
conn
->
request_info
);
}
if
(
conn
->
request_len
<
0
||
(
conn
->
request_len
==
0
||
io
->
len
>=
io
->
size
))
{
conn
->
flags
|=
CONN_CLOSE
;
}
else
if
(
conn
->
endpoint_type
==
EP_NONE
)
{
open_local_endpoint
(
conn
);
}
process_request
(
conn
);
}
}
void
add_to_set
(
sock_t
sock
,
fd_set
*
set
,
sock_t
*
max_fd
)
{
FD_SET
(
sock
,
set
);
if
(
sock
>
*
max_fd
)
{
*
max_fd
=
sock
;
}
static
int
should_keep_alive
(
const
struct
mg_connection
*
conn
)
{
const
char
*
method
=
conn
->
request_info
.
request_method
;
const
char
*
http_version
=
conn
->
request_info
.
http_version
;
const
char
*
header
=
mg_get_header
(
conn
,
"Connection"
);
return
method
!=
NULL
&&
!
strcmp
(
method
,
"GET"
)
&&
((
header
!=
NULL
&&
!
strcmp
(
header
,
"keep-alive"
))
||
(
header
==
NULL
&&
http_version
&&
!
strcmp
(
http_version
,
"1.1"
)));
}
static
int
io_space
(
const
struct
iobuf
*
io
)
{
return
io
->
size
-
io
->
len
;
static
void
close_local_endpoint
(
struct
mg_connection
*
conn
)
{
struct
iobuf
*
io
=
&
conn
->
local_iobuf
;
int
keep_alive
=
should_keep_alive
(
conn
);
// Must be done before memmove!
// Close file descriptor
switch
(
conn
->
endpoint_type
)
{
case
EP_FILE
:
close
(
conn
->
endpoint
.
fd
);
break
;
default:
assert
(
1
);
break
;
}
// Get rid of that request from the buffer. NOTE: order is important here
assert
(
conn
->
request_len
<=
io
->
len
);
memmove
(
io
->
buf
,
io
->
buf
+
conn
->
request_len
,
io
->
len
-
conn
->
request_len
);
io
->
len
-=
conn
->
request_len
;
conn
->
endpoint_type
=
EP_NONE
;
conn
->
request_len
=
0
;
if
(
keep_alive
)
{
DBG
((
"keep alive!"
));
process_request
(
conn
);
// Can call us recursively!
}
else
{
DBG
((
"closing!"
));
conn
->
flags
|=
conn
->
remote_iobuf
.
len
==
0
?
CONN_CLOSE
:
CONN_SPOOL_DONE
;
}
}
static
void
transfer_file_data
(
struct
mg_connection
*
conn
)
{
struct
iobuf
*
io
=
&
conn
->
remote_iobuf
,
*
iol
=
&
conn
->
local_iobuf
;
int
n
=
read
(
conn
->
endpoint
.
fd
,
io
->
buf
+
io
->
len
,
io
->
size
-
io
->
len
);
//DBG(("%s: %d", __func__, n));
struct
iobuf
*
io
=
&
conn
->
remote_iobuf
;
int
n
,
rem_space
=
io_space
(
io
);
if
(
rem_space
<=
0
)
return
;
n
=
read
(
conn
->
endpoint
.
fd
,
io
->
buf
+
io
->
len
,
rem_space
);
if
(
is_error
(
n
))
{
close
(
conn
->
endpoint
.
fd
);
conn
->
endpoint
.
fd
=
0
;
conn
->
endpoint_type
=
EP_NONE
;
memmove
(
iol
->
buf
,
iol
->
buf
+
conn
->
request_len
,
iol
->
len
-
conn
->
request_len
);
iol
->
len
-=
conn
->
request_len
;
conn
->
request_len
=
0
;
if
(
iol
->
len
<=
0
)
{
conn
->
flags
|=
io
->
len
>
0
?
CONN_SPOOL_DONE
:
CONN_CLOSE
;
}
else
{
DBG
((
"%s"
,
"more req!"
));
}
//DBG(("%s: %s", __func__, "YEEEEEE"));
//conn->flags |= io->len > 0 ? CONN_SPOOL_DONE : CONN_CLOSE;
close_local_endpoint
(
conn
);
}
else
if
(
n
>
0
)
{
io
->
len
+=
n
;
}
}
void
add_to_set
(
sock_t
sock
,
fd_set
*
set
,
sock_t
*
max_fd
)
{
FD_SET
(
sock
,
set
);
if
(
sock
>
*
max_fd
)
{
*
max_fd
=
sock
;
}
}
void
mg_poll_server
(
struct
mg_server
*
server
,
unsigned
int
milliseconds
)
{
struct
linked_list_link
*
lp
,
*
tmp
;
struct
mg_connection
*
conn
;
struct
timeval
tv
;
fd_set
read_set
,
write_set
;
sock_t
max_fd
=
-
1
;
time_t
current_time
=
time
(
NULL
),
expire_time
=
current_time
+
3
;
time_t
current_time
=
time
(
NULL
),
expire_time
=
current_time
+
atoi
(
server
->
config_options
[
IDLE_TIMEOUT_MS
])
/
1000
;
FD_ZERO
(
&
read_set
);
FD_ZERO
(
&
write_set
);
add_to_set
(
server
->
listening_sock
,
&
read_set
,
&
max_fd
);
add_to_set
(
server
->
ctl
[
0
],
&
read_set
,
&
max_fd
);
LINKED_LIST_FOREACH
(
&
server
->
active_connections
,
lp
,
tmp
)
{
conn
=
LINKED_LIST_ENTRY
(
lp
,
struct
mg_connection
,
link
);
add_to_set
(
conn
->
client_sock
,
&
read_set
,
&
max_fd
);
if
(
conn
->
endpoint_type
==
EP_FILE
&&
io_space
(
&
conn
->
remote_iobuf
)
>
0
)
{
if
(
conn
->
endpoint_type
==
EP_FILE
)
{
transfer_file_data
(
conn
);
// read can return 0, meaning EOF. Need to signal the writer to close.
add_to_set
(
conn
->
client_sock
,
&
write_set
,
&
max_fd
);
}
if
(
conn
->
remote_iobuf
.
len
>
0
)
{
add_to_set
(
conn
->
client_sock
,
&
write_set
,
&
max_fd
);
}
else
if
(
conn
->
flags
&
CONN_CLOSE
)
{
close_conn
(
conn
);
}
}
...
...
@@ -895,7 +950,6 @@ void mg_poll_server(struct mg_server *server, unsigned int milliseconds) {
read_from_client
(
conn
);
}
if
(
FD_ISSET
(
conn
->
client_sock
,
&
write_set
))
{
assert
(
conn
->
remote_iobuf
.
len
>=
0
);
conn
->
expire_time
=
expire_time
;
write_to_client
(
conn
);
}
...
...
@@ -942,6 +996,7 @@ struct mg_server *mg_create_server(const char *opts[], mg_event_handler_t func,
server
->
event_handler
=
func
;
server
->
user_data
=
user_data
;
LINKED_LIST_INIT
(
&
server
->
active_connections
);
mg_socketpair
(
server
->
ctl
);
while
(
opts
!=
NULL
&&
(
name
=
*
opts
++
)
!=
NULL
)
{
if
((
i
=
get_option_index
(
name
))
==
-
1
)
{
...
...
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