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
f105b74d
Commit
f105b74d
authored
Aug 31, 2010
by
valenok
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
experimental keep-alive, options defaults
parent
fed9ffc1
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
159 additions
and
113 deletions
+159
-113
main.c
main.c
+8
-3
mongoose.c
mongoose.c
+145
-108
mongoose.h
mongoose.h
+3
-2
test.pl
test/test.pl
+3
-0
No files found.
main.c
View file @
f105b74d
...
...
@@ -103,8 +103,9 @@ static void show_usage_and_exit(void) {
fprintf
(
stderr
,
"OPTIONS:
\n
"
);
names
=
mg_get_valid_option_names
();
for
(
i
=
0
;
names
[
i
]
!=
NULL
;
i
+=
2
)
{
fprintf
(
stderr
,
" -%s %s
\n
"
,
names
[
i
],
names
[
i
+
1
]);
for
(
i
=
0
;
names
[
i
]
!=
NULL
;
i
+=
3
)
{
fprintf
(
stderr
,
" -%s %s (default:
\"
%s
\"
)
\n
"
,
names
[
i
],
names
[
i
+
1
],
names
[
i
+
2
]
==
NULL
?
""
:
names
[
i
+
2
]);
}
fprintf
(
stderr
,
"See http://code.google.com/p/mongoose/wiki/MongooseManual"
" for more details.
\n
"
);
...
...
@@ -164,6 +165,7 @@ static void process_command_line_arguments(char *argv[], char **options) {
const
char
*
config_file
=
NULL
;
char
line
[
512
],
opt
[
512
],
val
[
512
],
path
[
PATH_MAX
],
*
p
;
FILE
*
fp
=
NULL
;
struct
stat
st
;
size_t
i
,
line_no
=
0
;
/* Should we use a config file ? */
...
...
@@ -175,6 +177,9 @@ static void process_command_line_arguments(char *argv[], char **options) {
snprintf
(
path
,
sizeof
(
path
),
"%.*s%s"
,
(
int
)
(
p
-
argv
[
0
])
+
1
,
argv
[
0
],
CONFIG_FILE
);
}
if
(
stat
(
path
,
&
st
)
==
0
)
{
config_file
=
path
;
}
}
/* If config file was set in command line and open failed, exit */
if
(
config_file
!=
NULL
&&
(
fp
=
fopen
(
config_file
,
"r"
))
==
NULL
)
{
...
...
mongoose.c
View file @
f105b74d
...
...
@@ -352,19 +352,31 @@ enum {
CGI_INTERPRETER
,
CGI_ENVIRONMENT
,
SSI_EXTENSIONS
,
AUTHENTICATION_DOMAIN
,
URI_PROTECTION
,
GLOBAL_PASSWORDS_FILE
,
PUT_DELETE_PASSWORDS_FILE
,
ACCESS_LOG_FILE
,
ERROR_LOG_FILE
,
ACCESS_CONTROL_LIST
,
RUN_AS_USER
,
EXTRA_MIME_TYPES
,
ENABLE_DIRECTORY_LISTING
,
NUM_THREADS
,
EXTRA_MIME_TYPES
,
ENABLE_DIRECTORY_LISTING
,
ENABLE_KEEP_ALIVE
,
NUM_THREADS
,
NUM_OPTIONS
};
// There are two entries for each option: a short and a long version.
static
const
char
*
option_names
[]
=
{
"r"
,
"document_root"
,
"p"
,
"listening_ports"
,
"i"
,
"index_files"
,
"s"
,
"ssl_certificate"
,
"C"
,
"cgi_extensions"
,
"I"
,
"cgi_interpreter"
,
"E"
,
"cgi_environment"
,
"S"
,
"ssi_extensions"
,
"R"
,
"authentication_domain"
,
"P"
,
"protect_uri"
,
"g"
,
"global_passwords_file"
,
"G"
,
"put_delete_passwords_file"
,
"a"
,
"access_log_file"
,
"e"
,
"error_log_file"
,
"l"
,
"access_control_list"
,
"u"
,
"run_as_user"
,
"m"
,
"extra_mime_types"
,
"d"
,
"enable_directory_listing"
,
"t"
,
"num_threads"
,
static
const
char
*
config_options
[]
=
{
"r"
,
"document_root"
,
"."
,
"p"
,
"listening_ports"
,
"8080"
,
"i"
,
"index_files"
,
"index.html,index.htm,index.cgi"
,
"s"
,
"ssl_certificate"
,
NULL
,
"C"
,
"cgi_extensions"
,
".cgi,.pl,.php"
,
"I"
,
"cgi_interpreter"
,
NULL
,
"E"
,
"cgi_environment"
,
NULL
,
"S"
,
"ssi_extensions"
,
".shtml,.shtm"
,
"R"
,
"authentication_domain"
,
"mydomain.com"
,
"P"
,
"protect_uri"
,
NULL
,
"g"
,
"global_passwords_file"
,
NULL
,
"G"
,
"put_delete_passwords_file"
,
NULL
,
"a"
,
"access_log_file"
,
NULL
,
"e"
,
"error_log_file"
,
NULL
,
"l"
,
"access_control_list"
,
NULL
,
"u"
,
"run_as_user"
,
NULL
,
"m"
,
"extra_mime_types"
,
NULL
,
"d"
,
"enable_directory_listing"
,
"yes"
,
"k"
,
"enable_keep_alive"
,
"no"
,
"t"
,
"num_threads"
,
"10"
,
NULL
};
...
...
@@ -402,7 +414,7 @@ struct mg_connection {
};
const
char
**
mg_get_valid_option_names
(
void
)
{
return
option_name
s
;
return
config_option
s
;
}
static
void
*
call_user
(
struct
mg_connection
*
conn
,
enum
mg_event
event
)
{
...
...
@@ -412,10 +424,11 @@ static void *call_user(struct mg_connection *conn, enum mg_event event) {
static
int
get_option_index
(
const
char
*
name
)
{
int
i
;
for
(
i
=
0
;
option_names
[
i
]
!=
NULL
;
i
+=
2
)
{
if
(
strcmp
(
option_names
[
i
],
name
)
==
0
||
strcmp
(
option_names
[
i
+
1
],
name
)
==
0
)
{
return
i
/
2
;
#define ENTRIES_PER_OPTION 3
for
(
i
=
0
;
config_options
[
i
]
!=
NULL
;
i
+=
ENTRIES_PER_OPTION
)
{
if
(
strcmp
(
config_options
[
i
],
name
)
==
0
||
strcmp
(
config_options
[
i
+
1
],
name
)
==
0
)
{
return
i
/
ENTRIES_PER_OPTION
;
}
}
return
-
1
;
...
...
@@ -448,7 +461,7 @@ static void cry(struct mg_connection *conn, const char *fmt, ...) {
// same way string option can.
conn
->
request_info
.
log_message
=
buf
;
if
(
call_user
(
conn
,
MG_EVENT_LOG
)
==
NULL
)
{
fp
=
conn
->
ctx
->
config
[
ERROR_LOG_FILE
]
==
NULL
?
stderr
:
fp
=
conn
->
ctx
->
config
[
ERROR_LOG_FILE
]
==
NULL
?
NULL
:
mg_fopen
(
conn
->
ctx
->
config
[
ERROR_LOG_FILE
],
"a+"
);
if
(
fp
!=
NULL
)
{
...
...
@@ -673,6 +686,17 @@ static int match_extension(const char *path, const char *ext_list) {
}
#endif // !NO_CGI
// HTTP 1.1 assumes keep alive if "Connection:" header is not set
static
int
should_keep_alive
(
const
struct
mg_connection
*
conn
)
{
const
char
*
header
=
mg_get_header
(
conn
,
"Connection"
);
return
(
header
==
NULL
&&
!
strcmp
(
conn
->
request_info
.
http_version
,
"1.1"
))
||
(
header
!=
NULL
&&
!
strcmp
(
header
,
"keep-alive"
));
}
static
const
char
*
suggest_connection_header
(
const
struct
mg_connection
*
conn
)
{
return
should_keep_alive
(
conn
)
?
"keep-alive"
:
"close"
;
}
static
void
send_http_error
(
struct
mg_connection
*
conn
,
int
status
,
const
char
*
reason
,
const
char
*
fmt
,
...)
{
char
buf
[
BUFSIZ
];
...
...
@@ -700,7 +724,8 @@ static void send_http_error(struct mg_connection *conn, int status,
mg_printf
(
conn
,
"HTTP/1.1 %d %s
\r\n
"
"Content-Type: text/plain
\r\n
"
"Content-Length: %d
\r\n
"
"Connection: close
\r\n\r\n
"
,
status
,
reason
,
len
);
"Connection: %s
\r\n\r\n
"
,
status
,
reason
,
len
,
suggest_connection_header
(
conn
));
conn
->
num_bytes_sent
+=
mg_printf
(
conn
,
"%s"
,
buf
);
}
}
...
...
@@ -1266,8 +1291,8 @@ static int pull(FILE *fp, SOCKET sock, SSL *ssl, char *buf, int len) {
}
int
mg_read
(
struct
mg_connection
*
conn
,
void
*
buf
,
size_t
len
)
{
int
n
,
buffered_
data_
len
,
nread
;
const
char
*
buffered
_data
;
int
n
,
buffered_len
,
nread
;
const
char
*
buffered
;
assert
(
conn
->
content_len
>=
conn
->
consumed_content
);
DEBUG_TRACE
((
"%p %zu %lld %lld"
,
buf
,
len
,
...
...
@@ -1283,21 +1308,21 @@ int mg_read(struct mg_connection *conn, void *buf, size_t len) {
}
// How many bytes of data we have buffered in the request buffer?
buffered
_data
=
conn
->
buf
+
conn
->
request_len
+
conn
->
consumed_content
;
buffered_
data_
len
=
conn
->
data_len
-
conn
->
request_len
;
assert
(
buffered_
data_
len
>=
0
);
buffered
=
conn
->
buf
+
conn
->
request_len
;
buffered_len
=
conn
->
data_len
-
conn
->
request_len
;
assert
(
buffered_len
>=
0
);
// Return buffered data back if we haven't done that yet.
if
(
conn
->
consumed_content
<
(
int64_t
)
buffered_
data_
len
)
{
buffered_
data_
len
-=
conn
->
consumed_content
;
if
(
len
<
(
size_t
)
buffered_
data_
len
)
{
buffered_
data_
len
=
len
;
if
(
conn
->
consumed_content
<
(
int64_t
)
buffered_len
)
{
buffered_len
-=
conn
->
consumed_content
;
if
(
len
<
(
size_t
)
buffered_len
)
{
buffered_len
=
len
;
}
memcpy
(
buf
,
buffered
_data
,
buffered_data
_len
);
len
-=
buffered_
data_
len
;
buf
=
(
char
*
)
buf
+
buffered_
data_
len
;
conn
->
consumed_content
+=
buffered_
data_
len
;
nread
=
buffered_
data_
len
;
memcpy
(
buf
,
buffered
,
buffered
_len
);
len
-=
buffered_len
;
buf
=
(
char
*
)
buf
+
buffered_len
;
conn
->
consumed_content
+=
buffered_len
;
nread
=
buffered_len
;
}
// We have returned all buffered data. Read new data from the remote socket.
...
...
@@ -2449,11 +2474,11 @@ static void handle_file_request(struct mg_connection *conn, const char *path,
"Etag:
\"
%s
\"\r\n
"
"Content-Type: %.*s
\r\n
"
"Content-Length: %"
INT64_FMT
"
\r\n
"
"Connection:
close
\r\n
"
"Connection:
%s
\r\n
"
"Accept-Ranges: bytes
\r\n
"
"%s
\r\n
"
,
conn
->
request_info
.
status_code
,
msg
,
date
,
lm
,
etag
,
mime_vec
.
len
,
mime_vec
.
ptr
,
cl
,
range
);
mime_vec
.
len
,
mime_vec
.
ptr
,
cl
,
suggest_connection_header
(
conn
),
range
);
if
(
strcmp
(
conn
->
request_info
.
request_method
,
"HEAD"
)
!=
0
)
{
send_file_data
(
conn
,
fp
,
cl
);
...
...
@@ -2487,6 +2512,11 @@ static int is_valid_http_method(const char *method) {
static
int
parse_http_request
(
char
*
buf
,
struct
mg_request_info
*
ri
)
{
int
status
=
0
;
// RFC says that all initial whitespaces should be ingored
while
(
*
buf
!=
'\0'
&&
isspace
(
*
(
unsigned
char
*
)
buf
))
{
buf
++
;
}
ri
->
request_method
=
skip
(
&
buf
,
" "
);
ri
->
uri
=
skip
(
&
buf
,
" "
);
ri
->
http_version
=
skip
(
&
buf
,
"
\r\n
"
);
...
...
@@ -2580,10 +2610,9 @@ static int is_not_modified(const struct mg_connection *conn,
}
static
int
handle_request_body
(
struct
mg_connection
*
conn
,
FILE
*
fp
)
{
const
char
*
expect
,
*
data
;
const
char
*
expect
,
*
buffered
;
char
buf
[
BUFSIZ
];
int
to_read
,
nread
,
data_len
;
int
success
=
0
;
int
to_read
,
nread
,
buffered_len
,
success
=
0
;
expect
=
mg_get_header
(
conn
,
"Expect"
);
assert
(
fp
!=
NULL
);
...
...
@@ -2596,16 +2625,19 @@ static int handle_request_body(struct mg_connection *conn, FILE *fp) {
if
(
expect
!=
NULL
)
{
(
void
)
mg_printf
(
conn
,
"%s"
,
"HTTP/1.1 100 Continue
\r\n\r\n
"
);
}
data
=
conn
->
buf
+
conn
->
request_len
;
data_len
=
conn
->
data_len
-
conn
->
request_len
;
assert
(
data_len
>=
0
);
if
(
conn
->
content_len
<=
(
int64_t
)
data_len
)
{
success
=
push
(
fp
,
INVALID_SOCKET
,
NULL
,
data
,
conn
->
content_len
)
==
conn
->
content_len
;
}
else
{
push
(
fp
,
INVALID_SOCKET
,
NULL
,
data
,
(
int64_t
)
data_len
);
conn
->
consumed_content
+=
data_len
;
buffered
=
conn
->
buf
+
conn
->
request_len
;
buffered_len
=
conn
->
data_len
-
conn
->
request_len
;
assert
(
buffered_len
>=
0
);
assert
(
conn
->
consumed_content
==
0
);
if
(
buffered_len
>
0
)
{
if
((
int64_t
)
buffered_len
>
conn
->
content_len
)
{
buffered_len
=
conn
->
content_len
;
}
push
(
fp
,
INVALID_SOCKET
,
NULL
,
buffered
,
(
int64_t
)
buffered_len
);
conn
->
consumed_content
+=
buffered_len
;
}
while
(
conn
->
consumed_content
<
conn
->
content_len
)
{
to_read
=
sizeof
(
buf
);
...
...
@@ -2618,10 +2650,10 @@ static int handle_request_body(struct mg_connection *conn, FILE *fp) {
}
conn
->
consumed_content
+=
nread
;
}
if
(
conn
->
consumed_content
==
conn
->
content_len
)
{
success
=
1
;
}
}
// Each error code path in this function must send an error
if
(
!
success
)
{
...
...
@@ -3088,8 +3120,9 @@ static void handle_ssi_file_request(struct mg_connection *conn,
strerror
(
ERRNO
));
}
else
{
set_close_on_exec
(
fileno
(
fp
));
(
void
)
mg_printf
(
conn
,
"%s"
,
"HTTP/1.1 200 OK
\r\n
"
"Content-Type: text/html
\r\n
Connection: close
\r\n\r\n
"
);
mg_printf
(
conn
,
"HTTP/1.1 200 OK
\r\n
"
"Content-Type: text/html
\r\n
Connection: %s
\r\n\r\n
"
,
suggest_connection_header
(
conn
));
send_ssi_file
(
conn
,
path
,
fp
,
0
);
(
void
)
fclose
(
fp
);
}
...
...
@@ -3505,17 +3538,19 @@ static void close_connection(struct mg_connection *conn) {
}
static
void
discard_current_request_from_buffer
(
struct
mg_connection
*
conn
)
{
int
over_len
,
body_len
;
char
*
buffered
;
int
buffered_len
,
body_len
;
over_len
=
conn
->
data_len
-
conn
->
request_len
;
assert
(
over_len
>=
0
);
buffered
=
conn
->
buf
+
conn
->
request_len
;
buffered_len
=
conn
->
data_len
-
conn
->
request_len
;
assert
(
buffered_len
>=
0
);
if
(
conn
->
content_len
==
-
1
)
{
body_len
=
0
;
}
else
if
(
conn
->
content_len
<
(
int64_t
)
over
_len
)
{
}
else
if
(
conn
->
content_len
<
(
int64_t
)
buffered
_len
)
{
body_len
=
(
int
)
conn
->
content_len
;
}
else
{
body_len
=
over
_len
;
body_len
=
buffered
_len
;
}
conn
->
data_len
-=
conn
->
request_len
+
body_len
;
...
...
@@ -3524,8 +3559,12 @@ static void discard_current_request_from_buffer(struct mg_connection *conn) {
static
void
process_new_connection
(
struct
mg_connection
*
conn
)
{
struct
mg_request_info
*
ri
=
&
conn
->
request_info
;
int
keep_alive_enabled
;
const
char
*
cl
;
keep_alive_enabled
=
!
strcmp
(
conn
->
ctx
->
config
[
ENABLE_KEEP_ALIVE
],
"yes"
);
do
{
reset_per_request_attributes
(
conn
);
// If next request is not pipelined, read it in
...
...
@@ -3558,6 +3597,7 @@ static void process_new_connection(struct mg_connection *conn) {
log_access
(
conn
);
discard_current_request_from_buffer
(
conn
);
}
}
while
(
keep_alive_enabled
&&
should_keep_alive
(
conn
));
}
// Worker threads take accepted socket from the queue
...
...
@@ -3788,15 +3828,6 @@ struct mg_context *mg_start(mg_callback_t user_callback, const char **options) {
ctx
=
calloc
(
1
,
sizeof
(
*
ctx
));
ctx
->
user_callback
=
user_callback
;
ctx
->
config
[
DOCUMENT_ROOT
]
=
mg_strdup
(
"."
);
ctx
->
config
[
LISTENING_PORTS
]
=
mg_strdup
(
"8080"
);
ctx
->
config
[
ENABLE_DIRECTORY_LISTING
]
=
mg_strdup
(
"yes"
);
ctx
->
config
[
AUTHENTICATION_DOMAIN
]
=
mg_strdup
(
"mydomain.com"
);
ctx
->
config
[
INDEX_FILES
]
=
mg_strdup
(
"index.html,index.htm,index.cgi"
);
ctx
->
config
[
CGI_EXTENSIONS
]
=
mg_strdup
(
".cgi,.pl,.php"
);
ctx
->
config
[
SSI_EXTENSIONS
]
=
mg_strdup
(
".shtml,.shtm"
);
ctx
->
config
[
NUM_THREADS
]
=
mg_strdup
(
"10"
);
while
((
name
=
*
options
++
)
!=
NULL
)
{
if
((
i
=
get_option_index
(
name
))
==
-
1
)
{
cry
(
fc
(
ctx
),
"Invalid option: %s"
,
name
);
...
...
@@ -3807,13 +3838,19 @@ struct mg_context *mg_start(mg_callback_t user_callback, const char **options) {
free_context
(
ctx
);
return
NULL
;
}
if
(
ctx
->
config
[
i
]
!=
NULL
)
{
free
(
ctx
->
config
[
i
]);
}
ctx
->
config
[
i
]
=
mg_strdup
(
value
);
DEBUG_TRACE
((
"[%s] -> [%s]"
,
name
,
value
));
}
// Set default value if needed
for
(
i
=
0
;
config_options
[
i
*
3
]
!=
NULL
;
i
++
)
{
if
(
ctx
->
config
[
i
]
==
NULL
&&
config_options
[
i
*
3
+
2
]
!=
NULL
)
{
ctx
->
config
[
i
]
=
mg_strdup
(
config_options
[
i
*
3
+
2
]);
DEBUG_TRACE
((
"Setting default: [%s] -> [%s]"
,
config_options
[
i
*
3
+
1
],
config_options
[
i
*
3
+
2
]));
}
}
// NOTE(lsm): order is important here. SSL certificates must
// be initialized before listening ports. UID must be set last.
if
(
!
set_ssl_option
(
ctx
)
||
...
...
mongoose.h
View file @
f105b74d
...
...
@@ -118,8 +118,9 @@ void mg_stop(struct mg_context *);
const
char
*
mg_get_option
(
const
struct
mg_context
*
ctx
,
const
char
*
name
);
// Return array of valid configuration options. For each option, a short
// version and a long version is returned. Array is NULL terminated.
// Return array of strings that represent valid configuration options.
// For each option, a short name, long name, and default value is returned.
// Array is NULL terminated.
const
char
**
mg_get_valid_option_names
(
void
);
...
...
test/test.pl
View file @
f105b74d
...
...
@@ -211,6 +211,9 @@ o("GET /$test_dir_uri/x/ HTTP/1.0\n\n", "Content-Type: text/html\r\n\r\n",
'index.cgi execution'
);
o
(
"GET /ta/x/ HTTP/1.0\n\n"
,
"SCRIPT_NAME=/ta/x/index.cgi"
,
'Aliases SCRIPT_NAME'
);
#o("GET /hello.txt HTTP/1.1\n\n GET /hello.txt HTTP/1.0\n\n",
# 'HTTP/1.1 200.+keep-alive.+HTTP/1.1 200.+close',
# 'Request pipelining', 2);
my
$mime_types
=
{
html
=>
'text/html'
,
...
...
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