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
b21a8b21
Commit
b21a8b21
authored
Jan 29, 2013
by
Sergey Lyubka
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Removed wait_until_socket_is_readable(). Rely on socket timeout.
parent
8bb49642
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
48 additions
and
95 deletions
+48
-95
mongoose.c
mongoose.c
+48
-95
No files found.
mongoose.c
View file @
b21a8b21
...
...
@@ -100,7 +100,7 @@ typedef long off_t;
#if defined(_MSC_VER) && _MSC_VER < 1300
#define STRX(x) #x
#define STR(x) STRX(x)
#define __func__
"line
" STR(__LINE__)
#define __func__
__FILE__ ":
" STR(__LINE__)
#define strtoull(x, y, z) strtoul(x, y, z)
#define strtoll(x, y, z) strtol(x, y, z)
#else
...
...
@@ -460,7 +460,7 @@ static const char *config_options[] = {
"u"
,
"run_as_user"
,
NULL
,
"w"
,
"url_rewrite_patterns"
,
NULL
,
"x"
,
"hide_files_patterns"
,
NULL
,
"z"
,
"request_timeout
"
,
NULL
,
"z"
,
"request_timeout
_ms"
,
"30000"
,
NULL
};
#define ENTRIES_PER_CONFIG_OPTION 3
...
...
@@ -1478,30 +1478,6 @@ static int64_t push(FILE *fp, SOCKET sock, SSL *ssl, const char *buf,
return
sent
;
}
// This function is needed to prevent Mongoose to be stuck in a blocking
// socket read when user requested exit. To do that, we sleep in select
// with a timeout, and when returned, check the context for the stop flag.
// If it is set, we return 0, and this means that we must not continue
// reading, must give up and close the connection and exit serving thread.
static
int
wait_until_socket_is_readable
(
struct
mg_connection
*
conn
)
{
int
result
;
struct
pollfd
pfd
;
do
{
pfd
.
fd
=
conn
->
client
.
sock
;
pfd
.
events
=
POLLIN
;
result
=
poll
(
&
pfd
,
1
,
200
);
#ifndef NO_SSL
if
(
result
==
0
&&
conn
->
ssl
!=
NULL
)
{
result
=
SSL_pending
(
conn
->
ssl
);
}
#endif
}
while
((
result
==
0
||
(
result
<
0
&&
ERRNO
==
EINTR
))
&&
conn
->
ctx
->
stop_flag
==
0
);
return
conn
->
ctx
->
stop_flag
||
result
<
0
?
0
:
1
;
}
// Read from IO channel - opened file descriptor, socket, or SSL descriptor.
// Return negative value on error, or number of bytes read on success.
static
int
pull
(
FILE
*
fp
,
struct
mg_connection
*
conn
,
char
*
buf
,
int
len
)
{
...
...
@@ -1512,8 +1488,6 @@ static int pull(FILE *fp, struct mg_connection *conn, char *buf, int len) {
// pipe, fread() may block until IO buffer is filled up. We cannot afford
// to block and must pass all read bytes immediately to the client.
nread
=
read
(
fileno
(
fp
),
buf
,
(
size_t
)
len
);
}
else
if
(
!
conn
->
must_close
&&
!
wait_until_socket_is_readable
(
conn
))
{
nread
=
-
1
;
#ifndef NO_SSL
}
else
if
(
conn
->
ssl
!=
NULL
)
{
nread
=
SSL_read
(
conn
->
ssl
,
buf
,
len
);
...
...
@@ -2912,22 +2886,16 @@ static int parse_http_message(char *buf, int len, struct mg_request_info *ri) {
// Upon every read operation, increase nread by the number of bytes read.
static
int
read_request
(
FILE
*
fp
,
struct
mg_connection
*
conn
,
char
*
buf
,
int
bufsiz
,
int
*
nread
)
{
int
request_len
,
n
=
1
;
int
request_len
,
n
=
0
;
request_len
=
get_request_len
(
buf
,
*
nread
);
while
(
*
nread
<
bufsiz
&&
request_len
==
0
&&
n
>
0
)
{
n
=
pull
(
fp
,
conn
,
buf
+
*
nread
,
bufsiz
-
*
nread
);
if
(
n
>
0
)
{
*
nread
+=
n
;
request_len
=
get_request_len
(
buf
,
*
nread
);
}
while
(
*
nread
<
bufsiz
&&
request_len
==
0
&&
(
n
=
pull
(
fp
,
conn
,
buf
+
*
nread
,
bufsiz
-
*
nread
))
>
0
)
{
*
nread
+=
n
;
request_len
=
get_request_len
(
buf
,
*
nread
);
}
if
(
n
<
0
)
{
// recv() error -> propagate error; do not process a b0rked-with-very-high-probability request
return
-
1
;
}
return
request_len
;
return
request_len
<=
0
&&
n
<=
0
?
-
1
:
request_len
;
}
// For given directory path, substitute it to valid index file.
...
...
@@ -3838,9 +3806,6 @@ static void read_websocket(struct mg_connection *conn) {
conn
->
data_len
-=
discard_len
;
conn
->
content_len
=
conn
->
consumed_content
=
0
;
}
else
{
if
(
wait_until_socket_is_readable
(
conn
)
==
0
)
{
break
;
}
n
=
pull
(
NULL
,
conn
,
conn
->
buf
+
conn
->
data_len
,
conn
->
buf_size
-
conn
->
data_len
);
if
(
n
<=
0
)
{
...
...
@@ -4352,23 +4317,6 @@ static int parse_port_string(const struct vec *vec, struct socket *so) {
return
1
;
}
static
int
set_timeout
(
struct
mg_context
*
ctx
,
SOCKET
sock
)
{
#ifndef _WIN32
struct
timeval
timeout
;
if
(
!
ctx
->
config
[
REQUEST_TIMEOUT
]
)
return
0
;
timeout
.
tv_sec
=
0
;
timeout
.
tv_usec
=
atoi
(
ctx
->
config
[
REQUEST_TIMEOUT
])
*
1000
;
#else
DWORD
timeout
;
if
(
!
ctx
->
config
[
REQUEST_TIMEOUT
]
)
return
0
;
timeout
=
atoi
(
ctx
->
config
[
REQUEST_TIMEOUT
]);
#endif
return
setsockopt
(
sock
,
SOL_SOCKET
,
SO_RCVTIMEO
,
(
void
*
)
&
timeout
,
sizeof
(
timeout
))
||
setsockopt
(
sock
,
SOL_SOCKET
,
SO_SNDTIMEO
,
(
void
*
)
&
timeout
,
sizeof
(
timeout
));
}
static
int
set_ports_option
(
struct
mg_context
*
ctx
)
{
const
char
*
list
=
ctx
->
config
[
LISTENING_PORTS
];
int
on
=
1
,
success
=
1
;
...
...
@@ -4380,31 +4328,20 @@ static int set_ports_option(struct mg_context *ctx) {
cry
(
fc
(
ctx
),
"%s: %.*s: invalid port spec. Expecting list of: %s"
,
__func__
,
(
int
)
vec
.
len
,
vec
.
ptr
,
"[IP_ADDRESS:]PORT[s|p]"
);
success
=
0
;
}
else
if
(
so
.
is_ssl
&&
(
ctx
->
ssl_ctx
==
NULL
||
ctx
->
config
[
SSL_CERTIFICATE
]
==
NULL
))
{
}
else
if
(
so
.
is_ssl
&&
ctx
->
ssl_ctx
==
NULL
)
{
cry
(
fc
(
ctx
),
"Cannot add SSL socket, is -ssl_certificate option set?"
);
success
=
0
;
}
else
if
((
so
.
sock
=
socket
(
so
.
lsa
.
sa
.
sa_family
,
SOCK_STREAM
,
6
))
==
INVALID_SOCKET
||
set_timeout
(
ctx
,
so
.
sock
)
||
// On Windows, SO_REUSEADDR is recommended only for
// broadcast UDP sockets
setsockopt
(
so
.
sock
,
SOL_SOCKET
,
SO_REUSEADDR
,
(
const
char
*
)
&
on
,
sizeof
(
on
))
!=
0
||
// Set TCP keep-alive. This is needed because if HTTP-level
// keep-alive is enabled, and client resets the connection,
// server won't get TCP FIN or RST and will keep the connection
// open forever. With TCP keep-alive, next keep-alive
// handshake will figure out that the client is down and
// will close the server end.
// Thanks to Igor Klopov who suggested the patch.
setsockopt
(
so
.
sock
,
SOL_SOCKET
,
SO_KEEPALIVE
,
(
char
*
)
&
on
,
sizeof
(
on
))
!=
0
||
setsockopt
(
so
.
sock
,
SOL_SOCKET
,
SO_REUSEADDR
,
(
void
*
)
&
on
,
sizeof
(
on
))
!=
0
||
bind
(
so
.
sock
,
&
so
.
lsa
.
sa
,
sizeof
(
so
.
lsa
))
!=
0
||
listen
(
so
.
sock
,
SOMAXCONN
)
!=
0
)
{
closesocket
(
so
.
sock
);
cry
(
fc
(
ctx
),
"%s: cannot bind to %.*s: %s"
,
__func__
,
(
int
)
vec
.
len
,
vec
.
ptr
,
strerror
(
ERRNO
));
closesocket
(
so
.
sock
);
success
=
0
;
}
else
{
set_close_on_exec
(
so
.
sock
);
...
...
@@ -5003,29 +4940,45 @@ static void produce_socket(struct mg_context *ctx, const struct socket *sp) {
(
void
)
pthread_mutex_unlock
(
&
ctx
->
mutex
);
}
static
int
set_sock_timeout
(
SOCKET
sock
,
int
milliseconds
)
{
#ifdef _WIN32
DWORD
t
=
milliseconds
;
#else
struct
timeval
t
;
t
.
tv_sec
=
milliseconds
/
1000
;
t
.
tv_usec
=
(
milliseconds
*
1000
)
%
1000000
;
#endif
return
setsockopt
(
sock
,
SOL_SOCKET
,
SO_RCVTIMEO
,
(
void
*
)
&
t
,
sizeof
(
t
))
||
setsockopt
(
sock
,
SOL_SOCKET
,
SO_SNDTIMEO
,
(
void
*
)
&
t
,
sizeof
(
t
));
}
static
void
accept_new_connection
(
const
struct
socket
*
listener
,
struct
mg_context
*
ctx
)
{
struct
socket
accepted
;
struct
socket
so
;
char
src_addr
[
20
];
socklen_t
len
;
int
allowed
;
len
=
sizeof
(
accepted
.
rsa
);
accepted
.
sock
=
accept
(
listener
->
sock
,
&
accepted
.
rsa
.
sa
,
&
len
);
if
(
accepted
.
sock
!=
INVALID_SOCKET
)
{
allowed
=
check_acl
(
ctx
,
ntohl
(
*
(
uint32_t
*
)
&
accepted
.
rsa
.
sin
.
sin_addr
));
if
(
allowed
)
{
// Put accepted socket structure into the queue
DEBUG_TRACE
((
"accepted socket %d"
,
accepted
.
sock
));
accepted
.
is_ssl
=
listener
->
is_ssl
;
accepted
.
ssl_redir
=
listener
->
ssl_redir
;
getsockname
(
accepted
.
sock
,
&
accepted
.
lsa
.
sa
,
&
len
);
produce_socket
(
ctx
,
&
accepted
);
}
else
{
sockaddr_to_string
(
src_addr
,
sizeof
(
src_addr
),
&
accepted
.
rsa
);
cry
(
fc
(
ctx
),
"%s: %s is not allowed to connect"
,
__func__
,
src_addr
);
(
void
)
closesocket
(
accepted
.
sock
);
}
socklen_t
len
=
sizeof
(
so
.
rsa
);
int
on
=
1
;
if
((
so
.
sock
=
accept
(
listener
->
sock
,
&
so
.
rsa
.
sa
,
&
len
))
==
INVALID_SOCKET
)
{
}
else
if
(
!
check_acl
(
ctx
,
ntohl
(
*
(
uint32_t
*
)
&
so
.
rsa
.
sin
.
sin_addr
)))
{
sockaddr_to_string
(
src_addr
,
sizeof
(
src_addr
),
&
so
.
rsa
);
cry
(
fc
(
ctx
),
"%s: %s is not allowed to connect"
,
__func__
,
src_addr
);
closesocket
(
so
.
sock
);
}
else
{
// Put so socket structure into the queue
DEBUG_TRACE
((
"Accepted socket %d"
,
(
int
)
so
.
sock
));
so
.
is_ssl
=
listener
->
is_ssl
;
so
.
ssl_redir
=
listener
->
ssl_redir
;
getsockname
(
so
.
sock
,
&
so
.
lsa
.
sa
,
&
len
);
// Set TCP keep-alive. This is needed because if HTTP-level keep-alive
// is enabled, and client resets the connection, server won't get
// TCP FIN or RST and will keep the connection open forever. With TCP
// keep-alive, next keep-alive handshake will figure out that the client
// is down and will close the server end.
// Thanks to Igor Klopov who suggested the patch.
setsockopt
(
so
.
sock
,
SOL_SOCKET
,
SO_KEEPALIVE
,
(
void
*
)
&
on
,
sizeof
(
on
));
set_sock_timeout
(
so
.
sock
,
atoi
(
ctx
->
config
[
REQUEST_TIMEOUT
]));
produce_socket
(
ctx
,
&
so
);
}
}
...
...
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