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
6083b9c5
Commit
6083b9c5
authored
Sep 09, 2014
by
Sergey Lyubka
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Updated to the recent skeleton. SSL address format changed
parent
83237a02
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
873 additions
and
856 deletions
+873
-856
server.c
examples/server.c
+509
-507
unit_test.c
examples/unit_test.c
+5
-4
websocket_chat.c
examples/websocket_chat/websocket_chat.c
+1
-1
websocket_echo_server.c
examples/websocket_echo_server/websocket_echo_server.c
+1
-1
Makefile
examples/ws_ssl/Makefile
+4
-6
net_skeleton.c
examples/ws_ssl/net_skeleton.c
+1
-1
net_skeleton.h
examples/ws_ssl/net_skeleton.h
+1
-1
ssl_wrapper.c
examples/ws_ssl/ssl_wrapper.c
+1
-1
ssl_wrapper.h
examples/ws_ssl/ssl_wrapper.h
+1
-1
mongoose.c
mongoose.c
+344
-327
mongoose.h
mongoose.h
+5
-6
No files found.
examples/server.c
View file @
6083b9c5
...
...
@@ -474,6 +474,7 @@ static void set_options(char *argv[]) {
// scripts can use relative paths.
chdir
(
mg_get_option
(
server
,
"document_root"
));
#if 0
// Add an ability to pass listening socket to mongoose
{
const char *env = getenv("MONGOOSE_LISTENING_SOCKET");
...
...
@@ -481,6 +482,7 @@ static void set_options(char *argv[]) {
mg_set_listening_socket(server, atoi(env));
}
}
#endif
// Setup signal handler: quit on Ctrl-C
signal
(
SIGTERM
,
signal_handler
);
...
...
examples/unit_test.c
View file @
6083b9c5
...
...
@@ -396,9 +396,9 @@ static const char *test_server(void) {
ASSERT
(
mg_set_option
(
server
,
"listening_port"
,
LISTENING_ADDR
)
==
NULL
);
ASSERT
(
mg_set_option
(
server
,
"document_root"
,
"."
)
==
NULL
);
ASSERT
((
conn
=
mg_connect
(
server
,
"127.0.0.1
"
,
atoi
(
HTTP_PORT
),
0
))
!=
NULL
);
ASSERT
((
conn
=
mg_connect
(
server
,
"127.0.0.1
:"
HTTP_PORT
))
!=
NULL
);
conn
->
connection_param
=
buf1
;
ASSERT
((
conn
=
mg_connect
(
server
,
"127.0.0.1
"
,
atoi
(
HTTP_PORT
),
0
))
!=
NULL
);
ASSERT
((
conn
=
mg_connect
(
server
,
"127.0.0.1
:"
HTTP_PORT
))
!=
NULL
);
conn
->
connection_param
=
buf2
;
{
int
i
;
for
(
i
=
0
;
i
<
50
;
i
++
)
mg_poll_server
(
server
,
1
);
}
...
...
@@ -483,7 +483,7 @@ static const char *test_mg_set_option(void) {
}
static
const
char
*
test_rewrites
(
void
)
{
char
buf1
[
100
]
=
"xx"
;
char
buf1
[
100
]
=
"xx"
,
addr
[
50
]
;
struct
mg_server
*
server
=
mg_create_server
(
NULL
,
evh2
);
struct
mg_connection
*
conn
;
const
char
*
port
;
...
...
@@ -492,7 +492,8 @@ static const char *test_rewrites(void) {
ASSERT
(
mg_set_option
(
server
,
"document_root"
,
"."
)
==
NULL
);
ASSERT
(
mg_set_option
(
server
,
"url_rewrites"
,
"/xx=unit_test.c"
)
==
NULL
);
ASSERT
((
port
=
mg_get_option
(
server
,
"listening_port"
))
!=
NULL
);
ASSERT
((
conn
=
mg_connect
(
server
,
"127.0.0.1"
,
atoi
(
port
),
0
))
!=
NULL
);
snprintf
(
addr
,
sizeof
(
addr
),
"127.0.0.1:%s"
,
port
);
ASSERT
((
conn
=
mg_connect
(
server
,
addr
))
!=
NULL
);
conn
->
connection_param
=
buf1
;
{
int
i
;
for
(
i
=
0
;
i
<
50
;
i
++
)
mg_poll_server
(
server
,
1
);
}
...
...
examples/websocket_chat/websocket_chat.c
View file @
6083b9c5
// Copyright (c) 2013-2014 Cesanta Software Limited
// $Date: 2014-09-0
8 22:30:52
UTC $
// $Date: 2014-09-0
9 17:07:55
UTC $
#include <string.h>
#include <time.h>
...
...
examples/websocket_echo_server/websocket_echo_server.c
View file @
6083b9c5
// Copyright (c) 2013-2014 Cesanta Software Limited
// $Date: 2014-09-09
08:27:3
5 UTC $
// $Date: 2014-09-09
17:07:5
5 UTC $
#include <string.h>
#include <time.h>
...
...
examples/ws_ssl/Makefile
View file @
6083b9c5
# Copyright (c) 2014 Cesanta Software
# All rights reserved
CFLAGS
=
-W
-Wall
-I
../..
-g
-O0
$(CFLAGS_EXTRA)
NS
=
../../../net_skeleton
SW
=
../../../ssl_wrapper
CFLAGS
=
-W
-Wall
-I
../..
-I
.
-g
-O0
$(CFLAGS_EXTRA)
SOURCES
=
ws_ssl.c ../../mongoose.c
$(NS)
/net_skeleton.c
$(SW)
/
ssl_wrapper.c
SOURCES
=
ws_ssl.c ../../mongoose.c
net_skeleton.c
ssl_wrapper.c
PROG
=
ws_ssl
all
:
$(PROG)
$(PROG)
:
$(SOURCES)
$(CC)
-o
$(PROG)
$(SOURCES)
\
-
I
$(NS)
-
DNS_ENABLE_SSL
-DNOEMBED_NET_SKELETON
\
-
I
$(SW)
-
DSSL_WRAPPER_USE_AS_LIBRARY
-lssl
$(CFLAGS)
-DNS_ENABLE_SSL
-DNOEMBED_NET_SKELETON
\
-DSSL_WRAPPER_USE_AS_LIBRARY
-lssl
$(CFLAGS)
clean
:
rm
-rf
$(PROG)
*
.exe
*
.dSYM
*
.obj
*
.exp .
*
o
*
.lib
examples/ws_ssl/net_skeleton.c
View file @
6083b9c5
...
...
@@ -14,7 +14,7 @@
// Alternatively, you can license this software under a commercial
// license, as set out in <http://cesanta.com/>.
//
// $Date: 2014-09-09 1
6:03:50
UTC $
// $Date: 2014-09-09 1
7:07:55
UTC $
#include "net_skeleton.h"
...
...
examples/ws_ssl/net_skeleton.h
View file @
6083b9c5
...
...
@@ -14,7 +14,7 @@
// Alternatively, you can license this software under a commercial
// license, as set out in <http://cesanta.com/>.
//
// $Date: 2014-09-09 1
6:03:50
UTC $
// $Date: 2014-09-09 1
7:07:55
UTC $
#ifndef NS_SKELETON_HEADER_INCLUDED
#define NS_SKELETON_HEADER_INCLUDED
...
...
examples/ws_ssl/ssl_wrapper.c
View file @
6083b9c5
...
...
@@ -14,7 +14,7 @@
// Alternatively, you can license this software under a commercial
// license, as set out in <http://cesanta.com/products.html>.
//
// $Date: 2014-09-09 1
6:03:50
UTC $
// $Date: 2014-09-09 1
7:07:55
UTC $
#include "net_skeleton.h"
#include "ssl_wrapper.h"
...
...
examples/ws_ssl/ssl_wrapper.h
View file @
6083b9c5
...
...
@@ -14,7 +14,7 @@
// Alternatively, you can license this software under a commercial
// license, as set out in <http://cesanta.com/products.html>.
//
// $Date: 2014-09-09 1
6:03:50
UTC $
// $Date: 2014-09-09 1
7:07:55
UTC $
#ifndef SSL_WRAPPER_HEADER_INCLUDED
#define SSL_WRAPPER_HEADER_INCLUDED
...
...
mongoose.c
View file @
6083b9c5
...
...
@@ -15,7 +15,7 @@
// Alternatively, you can license this library under a commercial
// license, as set out in <http://cesanta.com/>.
//
// $Date: 2014-09-0
1 19:53:26
UTC $
// $Date: 2014-09-0
9 17:07:55
UTC $
#ifdef NOEMBED_NET_SKELETON
#include "net_skeleton.h"
...
...
@@ -36,11 +36,13 @@
//
// Alternatively, you can license this software under a commercial
// license, as set out in <http://cesanta.com/>.
//
// $Date: 2014-09-09 17:07:55 UTC $
#ifndef NS_SKELETON_HEADER_INCLUDED
#define NS_SKELETON_HEADER_INCLUDED
#define NS_SKELETON_VERSION "
1.1
"
#define NS_SKELETON_VERSION "
2.0.0
"
#undef UNICODE // Use ANSI WinAPI functions
#undef _UNICODE // Use multibyte encoding on Windows
...
...
@@ -133,7 +135,9 @@ typedef int sock_t;
#define DBG(x)
#endif
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
#endif
#ifdef NS_ENABLE_SSL
#ifdef __APPLE__
...
...
@@ -174,7 +178,7 @@ void iobuf_remove(struct iobuf *, size_t data_size);
// Net skeleton interface
// Events. Meaning of event parameter (evp) is given in the comment.
enum
ns_event
{
NS_POLL
,
// Sent to each connection on each call to ns_
serve
r_poll()
NS_POLL
,
// Sent to each connection on each call to ns_
mg
r_poll()
NS_ACCEPT
,
// New connection accept()-ed. union socket_address *remote_addr
NS_CONNECT
,
// connect() succeeded or failed. int *success_status
NS_RECV
,
// Data has benn received. int *num_bytes
...
...
@@ -187,36 +191,37 @@ enum ns_event {
struct
ns_connection
;
typedef
void
(
*
ns_callback_t
)(
struct
ns_connection
*
,
enum
ns_event
,
void
*
evp
);
struct
ns_server
{
void
*
server_data
;
sock_t
listening_sock
;
struct
ns_mgr
{
struct
ns_connection
*
active_connections
;
ns_callback_t
callback
;
SSL_CTX
*
ssl_ctx
;
SSL_CTX
*
client_ssl_ctx
;
const
char
*
hexdump_file
;
sock_t
ctl
[
2
];
ns_callback_t
callback
;
// Event handler function
const
char
*
hexdump_file
;
// Debug hexdump file path
sock_t
ctl
[
2
];
// Socketpair for mg_wakeup()
void
*
user_data
;
// User data
};
struct
ns_connection
{
struct
ns_connection
*
prev
,
*
next
;
struct
ns_server
*
server
;
struct
ns_connection
*
next
,
*
prev
;
// ns_mgr::active_connections linkage
struct
ns_connection
*
listener
;
// Set only for accept()-ed connections
struct
ns_mgr
*
mgr
;
sock_t
sock
;
union
socket_address
sa
;
struct
iobuf
recv_iobuf
;
struct
iobuf
send_iobuf
;
SSL
*
ssl
;
SSL_CTX
*
ssl_ctx
;
void
*
connection_data
;
time_t
last_io_time
;
unsigned
int
flags
;
#define NSF_FINISHED_SENDING_DATA (1 << 0)
#define NSF_BUFFER_BUT_DONT_SEND (1 << 1)
#define NSF_SSL_HANDSHAKE_DONE (1 << 2)
#define NSF_CONNECTING (1 << 3)
#define NSF_CLOSE_IMMEDIATELY (1 << 4)
#define NSF_ACCEPTED (1 << 5)
#define NSF_WANT_READ (1 << 6)
#define NSF_WANT_WRITE (1 << 7)
#define NSF_WANT_READ (1 << 5)
#define NSF_WANT_WRITE (1 << 6)
#define NSF_LISTENING (1 << 7)
#define NSF_UDP (1 << 8)
#define NSF_USER_1 (1 << 26)
#define NSF_USER_2 (1 << 27)
...
...
@@ -226,20 +231,15 @@ struct ns_connection {
#define NSF_USER_6 (1 << 31)
};
void
ns_server_init
(
struct
ns_server
*
,
void
*
server_data
,
ns_callback_t
);
void
ns_server_free
(
struct
ns_server
*
);
int
ns_server_poll
(
struct
ns_server
*
,
int
milli
);
void
ns_server_wakeup
(
struct
ns_server
*
);
void
ns_server_wakeup_ex
(
struct
ns_server
*
,
ns_callback_t
,
void
*
,
size_t
);
void
ns_iterate
(
struct
ns_server
*
,
ns_callback_t
cb
,
void
*
param
);
struct
ns_connection
*
ns_next
(
struct
ns_server
*
,
struct
ns_connection
*
);
struct
ns_connection
*
ns_add_sock
(
struct
ns_server
*
,
sock_t
sock
,
void
*
p
);
int
ns_bind
(
struct
ns_server
*
,
const
char
*
addr
);
int
ns_set_ssl_cert
(
struct
ns_server
*
,
const
char
*
ssl_cert
);
int
ns_set_ssl_ca_cert
(
struct
ns_server
*
,
const
char
*
ssl_ca_cert
);
struct
ns_connection
*
ns_connect
(
struct
ns_server
*
,
const
char
*
host
,
int
port
,
int
ssl
,
void
*
connection_param
);
void
ns_mgr_init
(
struct
ns_mgr
*
,
void
*
data
,
ns_callback_t
);
void
ns_mgr_free
(
struct
ns_mgr
*
);
int
ns_mgr_poll
(
struct
ns_mgr
*
,
int
milli
);
void
ns_broadcast
(
struct
ns_mgr
*
,
ns_callback_t
,
void
*
,
size_t
);
struct
ns_connection
*
ns_next
(
struct
ns_mgr
*
,
struct
ns_connection
*
);
struct
ns_connection
*
ns_add_sock
(
struct
ns_mgr
*
,
sock_t
sock
,
void
*
p
);
struct
ns_connection
*
ns_bind
(
struct
ns_mgr
*
,
const
char
*
addr
,
void
*
p
);
struct
ns_connection
*
ns_connect
(
struct
ns_mgr
*
,
const
char
*
addr
,
void
*
p
);
int
ns_send
(
struct
ns_connection
*
,
const
void
*
buf
,
int
len
);
int
ns_printf
(
struct
ns_connection
*
,
const
char
*
fmt
,
...);
...
...
@@ -253,6 +253,7 @@ void ns_set_close_on_exec(sock_t);
void
ns_sock_to_str
(
sock_t
sock
,
char
*
buf
,
size_t
len
,
int
flags
);
int
ns_hexdump
(
const
void
*
buf
,
int
len
,
char
*
dst
,
int
dst_len
);
int
ns_avprintf
(
char
**
buf
,
size_t
size
,
const
char
*
fmt
,
va_list
ap
);
int
ns_resolve
(
const
char
*
domain_name
,
char
*
ip_addr_buf
,
size_t
buf_len
);
#ifdef __cplusplus
}
...
...
@@ -274,6 +275,8 @@ int ns_avprintf(char **buf, size_t size, const char *fmt, va_list ap);
//
// Alternatively, you can license this software under a commercial
// license, as set out in <http://cesanta.com/>.
//
// $Date: 2014-09-09 17:07:55 UTC $
#ifndef NS_MALLOC
...
...
@@ -288,6 +291,9 @@ int ns_avprintf(char **buf, size_t size, const char *fmt, va_list ap);
#define NS_FREE free
#endif
#define NS_UDP_RECEIVE_BUFFER_SIZE 2000
#define NS_VPRINTF_BUFFER_SIZE 500
struct
ctl_msg
{
ns_callback_t
callback
;
char
message
[
1024
*
8
];
...
...
@@ -338,6 +344,16 @@ void iobuf_remove(struct iobuf *io, size_t n) {
}
}
static
size_t
ns_out
(
struct
ns_connection
*
nc
,
const
void
*
buf
,
size_t
len
)
{
if
(
nc
->
flags
&
NSF_UDP
)
{
long
n
=
send
(
nc
->
sock
,
buf
,
len
,
0
);
DBG
((
"%p %d send %ld (%d)"
,
nc
,
nc
->
sock
,
n
,
errno
));
return
n
<
0
?
0
:
n
;
}
else
{
return
iobuf_append
(
&
nc
->
send_iobuf
,
buf
,
len
);
}
}
#ifndef NS_DISABLE_THREADS
void
*
ns_start_thread
(
void
*
(
*
f
)(
void
*
),
void
*
p
)
{
#ifdef _WIN32
...
...
@@ -361,15 +377,15 @@ void *ns_start_thread(void *(*f)(void *), void *p) {
}
#endif // NS_DISABLE_THREADS
static
void
ns_add_conn
(
struct
ns_
server
*
serve
r
,
struct
ns_connection
*
c
)
{
c
->
next
=
serve
r
->
active_connections
;
serve
r
->
active_connections
=
c
;
static
void
ns_add_conn
(
struct
ns_
mgr
*
mg
r
,
struct
ns_connection
*
c
)
{
c
->
next
=
mg
r
->
active_connections
;
mg
r
->
active_connections
=
c
;
c
->
prev
=
NULL
;
if
(
c
->
next
!=
NULL
)
c
->
next
->
prev
=
c
;
}
static
void
ns_remove_conn
(
struct
ns_connection
*
conn
)
{
if
(
conn
->
prev
==
NULL
)
conn
->
serve
r
->
active_connections
=
conn
->
next
;
if
(
conn
->
prev
==
NULL
)
conn
->
mg
r
->
active_connections
=
conn
->
next
;
if
(
conn
->
prev
)
conn
->
prev
->
next
=
conn
->
next
;
if
(
conn
->
next
)
conn
->
next
->
prev
=
conn
->
prev
;
}
...
...
@@ -412,12 +428,12 @@ int ns_avprintf(char **buf, size_t size, const char *fmt, va_list ap) {
return
len
;
}
int
ns_vprintf
(
struct
ns_connection
*
conn
,
const
char
*
fmt
,
va_list
ap
)
{
char
mem
[
2000
],
*
buf
=
mem
;
int
ns_vprintf
(
struct
ns_connection
*
nc
,
const
char
*
fmt
,
va_list
ap
)
{
char
mem
[
NS_VPRINTF_BUFFER_SIZE
],
*
buf
=
mem
;
int
len
;
if
((
len
=
ns_avprintf
(
&
buf
,
sizeof
(
mem
),
fmt
,
ap
))
>
0
)
{
iobuf_append
(
&
conn
->
send_iobuf
,
buf
,
len
);
ns_out
(
nc
,
buf
,
len
);
}
if
(
buf
!=
mem
&&
buf
!=
NULL
)
{
free
(
buf
);
...
...
@@ -450,7 +466,7 @@ static void hexdump(struct ns_connection *nc, const char *path,
ev
==
NS_RECV
?
"<-"
:
ev
==
NS_SEND
?
"->"
:
ev
==
NS_ACCEPT
?
"<A"
:
ev
==
NS_CONNECT
?
"C>"
:
"XX"
,
dst
,
num_bytes
);
if
(
num_bytes
>
0
&&
(
buf
=
(
char
*
)
malloc
(
buf_size
))
!=
NULL
)
{
if
(
num_bytes
>
0
&&
(
buf
=
(
char
*
)
NS_MALLOC
(
buf_size
))
!=
NULL
)
{
ns_hexdump
(
io
->
buf
+
(
ev
==
NS_SEND
?
0
:
io
->
len
)
-
(
ev
==
NS_SEND
?
0
:
num_bytes
),
num_bytes
,
buf
,
buf_size
);
fprintf
(
fp
,
"%s"
,
buf
);
...
...
@@ -461,17 +477,14 @@ static void hexdump(struct ns_connection *nc, const char *path,
}
static
void
ns_call
(
struct
ns_connection
*
conn
,
enum
ns_event
ev
,
void
*
p
)
{
if
(
conn
->
serve
r
->
hexdump_file
!=
NULL
&&
ev
!=
NS_POLL
)
{
if
(
conn
->
mg
r
->
hexdump_file
!=
NULL
&&
ev
!=
NS_POLL
)
{
int
len
=
(
ev
==
NS_RECV
||
ev
==
NS_SEND
)
?
*
(
int
*
)
p
:
0
;
hexdump
(
conn
,
conn
->
serve
r
->
hexdump_file
,
len
,
ev
);
hexdump
(
conn
,
conn
->
mg
r
->
hexdump_file
,
len
,
ev
);
}
if
(
conn
->
server
->
callback
)
conn
->
serve
r
->
callback
(
conn
,
ev
,
p
);
if
(
conn
->
mgr
->
callback
)
conn
->
mg
r
->
callback
(
conn
,
ev
,
p
);
}
static
void
ns_close_conn
(
struct
ns_connection
*
conn
)
{
DBG
((
"%p %d"
,
conn
,
conn
->
flags
));
ns_call
(
conn
,
NS_CLOSE
,
NULL
);
ns_remove_conn
(
conn
);
static
void
ns_destroy_conn
(
struct
ns_connection
*
conn
)
{
closesocket
(
conn
->
sock
);
iobuf_free
(
&
conn
->
recv_iobuf
);
iobuf_free
(
&
conn
->
send_iobuf
);
...
...
@@ -479,10 +492,20 @@ static void ns_close_conn(struct ns_connection *conn) {
if
(
conn
->
ssl
!=
NULL
)
{
SSL_free
(
conn
->
ssl
);
}
if
(
conn
->
ssl_ctx
!=
NULL
)
{
SSL_CTX_free
(
conn
->
ssl_ctx
);
}
#endif
NS_FREE
(
conn
);
}
static
void
ns_close_conn
(
struct
ns_connection
*
conn
)
{
DBG
((
"%p %d"
,
conn
,
conn
->
flags
));
ns_call
(
conn
,
NS_CLOSE
,
NULL
);
ns_remove_conn
(
conn
);
ns_destroy_conn
(
conn
);
}
void
ns_set_close_on_exec
(
sock_t
sock
)
{
#ifdef _WIN32
(
void
)
SetHandleInformation
((
HANDLE
)
sock
,
HANDLE_FLAG_INHERIT
,
0
);
...
...
@@ -543,10 +566,31 @@ int ns_socketpair(sock_t sp[2]) {
}
#endif // NS_DISABLE_SOCKETPAIR
// Valid listening port spec is: [ip_address:]port, e.g. "80", "127.0.0.1:3128"
static
int
ns_parse_port_string
(
const
char
*
str
,
union
socket_address
*
sa
)
{
// TODO(lsm): use non-blocking resolver
static
int
ns_resolve2
(
const
char
*
host
,
struct
in_addr
*
ina
)
{
struct
hostent
*
he
;
if
((
he
=
gethostbyname
(
host
))
==
NULL
)
{
DBG
((
"gethostbyname(%s) failed: %s"
,
host
,
strerror
(
errno
)));
}
else
{
memcpy
(
ina
,
he
->
h_addr_list
[
0
],
sizeof
(
*
ina
));
return
1
;
}
return
0
;
}
// Resolve FDQN "host", store IP address in the "ip".
// Return > 0 (IP address length) on success.
int
ns_resolve
(
const
char
*
host
,
char
*
buf
,
size_t
n
)
{
struct
in_addr
ad
;
return
ns_resolve2
(
host
,
&
ad
)
?
snprintf
(
buf
,
n
,
"%s"
,
inet_ntoa
(
ad
))
:
0
;
}
// Address format: [PROTO://][IP_ADDRESS:]PORT[:CERT][:CA_CERT]
static
int
ns_parse_address
(
const
char
*
str
,
union
socket_address
*
sa
,
int
*
proto
,
int
*
use_ssl
,
char
*
cert
,
char
*
ca
)
{
unsigned
int
a
,
b
,
c
,
d
,
port
;
int
len
=
0
;
int
n
=
0
,
len
=
0
;
char
host
[
200
];
#ifdef NS_ENABLE_IPV6
char
buf
[
100
];
#endif
...
...
@@ -557,36 +601,57 @@ static int ns_parse_port_string(const char *str, union socket_address *sa) {
memset
(
sa
,
0
,
sizeof
(
*
sa
));
sa
->
sin
.
sin_family
=
AF_INET
;
*
proto
=
SOCK_STREAM
;
*
use_ssl
=
0
;
cert
[
0
]
=
ca
[
0
]
=
'\0'
;
if
(
memcmp
(
str
,
"ssl://"
,
6
)
==
0
)
{
str
+=
6
;
*
use_ssl
=
1
;
}
else
if
(
memcmp
(
str
,
"udp://"
,
6
)
==
0
)
{
str
+=
6
;
*
proto
=
SOCK_DGRAM
;
}
else
if
(
memcmp
(
str
,
"tcp://"
,
6
)
==
0
)
{
str
+=
6
;
}
if
(
sscanf
(
str
,
"%u.%u.%u.%u:%u%n"
,
&
a
,
&
b
,
&
c
,
&
d
,
&
port
,
&
len
)
==
5
)
{
// Bind to a specific IPv4 address, e.g. 192.168.1.5:8080
sa
->
sin
.
sin_addr
.
s_addr
=
htonl
((
a
<<
24
)
|
(
b
<<
16
)
|
(
c
<<
8
)
|
d
);
sa
->
sin
.
sin_port
=
htons
((
uint16_t
)
port
);
#ifdef NS_ENABLE_IPV6
}
else
if
(
sscanf
(
str
,
"[%
4
9[^]]]:%u%n"
,
buf
,
&
port
,
&
len
)
==
2
&&
}
else
if
(
sscanf
(
str
,
"[%
9
9[^]]]:%u%n"
,
buf
,
&
port
,
&
len
)
==
2
&&
inet_pton
(
AF_INET6
,
buf
,
&
sa
->
sin6
.
sin6_addr
))
{
// IPv6 address, e.g. [3ffe:2a00:100:7031::1]:8080
sa
->
sin6
.
sin6_family
=
AF_INET6
;
sa
->
sin6
.
sin6_port
=
htons
((
uint16_t
)
port
);
#endif
}
else
if
(
sscanf
(
str
,
"%199[^ :]:%u%n"
,
host
,
&
port
,
&
len
)
==
2
)
{
sa
->
sin
.
sin_port
=
htons
((
uint16_t
)
port
);
ns_resolve2
(
host
,
&
sa
->
sin
.
sin_addr
);
}
else
if
(
sscanf
(
str
,
"%u%n"
,
&
port
,
&
len
)
==
1
)
{
// If only port is specified, bind to IPv4, INADDR_ANY
sa
->
sin
.
sin_port
=
htons
((
uint16_t
)
port
);
}
else
{
port
=
0
;
// Parsing failure. Make port invalid.
}
return
port
<=
0xffff
&&
str
[
len
]
==
'\0'
;
if
(
*
use_ssl
&&
(
sscanf
(
str
+
len
,
":%99[^:]:%99[^:]%n"
,
cert
,
ca
,
&
n
)
==
2
||
sscanf
(
str
+
len
,
":%99[^:]%n"
,
cert
,
&
n
)
==
1
))
{
len
+=
n
;
}
return
port
<
0xffff
&&
str
[
len
]
==
'\0'
?
len
:
0
;
}
// 'sa' must be an initialized address to bind to
static
sock_t
ns_open_listening_socket
(
union
socket_address
*
sa
)
{
socklen_t
len
=
sizeof
(
*
sa
);
static
sock_t
ns_open_listening_socket
(
union
socket_address
*
sa
,
int
proto
)
{
socklen_t
sa_len
=
(
sa
->
sa
.
sa_family
==
AF_INET
)
?
sizeof
(
sa
->
sin
)
:
sizeof
(
sa
->
sin6
);
sock_t
sock
=
INVALID_SOCKET
;
#ifndef _WIN32
int
on
=
1
;
#endif
if
((
sock
=
socket
(
sa
->
sa
.
sa_family
,
SOCK_STREAM
,
6
))
!=
INVALID_SOCKET
&&
if
((
sock
=
socket
(
sa
->
sa
.
sa_family
,
proto
,
0
))
!=
INVALID_SOCKET
&&
#ifndef _WIN32
// SO_RESUSEADDR is not enabled on Windows because the semantics of
// SO_REUSEADDR on UNIX and Windows is different. On Windows,
...
...
@@ -596,12 +661,11 @@ static sock_t ns_open_listening_socket(union socket_address *sa) {
// scenarios. Therefore, SO_REUSEADDR was disabled on Windows.
!
setsockopt
(
sock
,
SOL_SOCKET
,
SO_REUSEADDR
,
(
void
*
)
&
on
,
sizeof
(
on
))
&&
#endif
!
bind
(
sock
,
&
sa
->
sa
,
sa
->
sa
.
sa_family
==
AF_INET
?
sizeof
(
sa
->
sin
)
:
sizeof
(
sa
->
sin6
))
&&
!
listen
(
sock
,
SOMAXCONN
))
{
!
bind
(
sock
,
&
sa
->
sa
,
sa_len
)
&&
(
proto
==
SOCK_DGRAM
||
listen
(
sock
,
SOMAXCONN
)
==
0
))
{
ns_set_non_blocking_mode
(
sock
);
// In case port was set to 0, get the real port number
(
void
)
getsockname
(
sock
,
&
sa
->
sa
,
&
len
);
(
void
)
getsockname
(
sock
,
&
sa
->
sa
,
&
sa_
len
);
}
else
if
(
sock
!=
INVALID_SOCKET
)
{
closesocket
(
sock
);
sock
=
INVALID_SOCKET
;
...
...
@@ -610,80 +674,97 @@ static sock_t ns_open_listening_socket(union socket_address *sa) {
return
sock
;
}
// Certificate generation script is at
// https://github.com/cesanta/net_skeleton/blob/master/examples/gen_certs.sh
int
ns_set_ssl_ca_cert
(
struct
ns_server
*
server
,
const
char
*
cert
)
{
#ifdef NS_ENABLE_SSL
STACK_OF
(
X509_NAME
)
*
list
=
SSL_load_client_CA_file
(
cert
);
if
(
cert
!=
NULL
&&
server
->
ssl_ctx
!=
NULL
&&
list
!=
NULL
)
{
SSL_CTX_set_client_CA_list
(
server
->
ssl_ctx
,
list
);
SSL_CTX_set_verify
(
server
->
ssl_ctx
,
SSL_VERIFY_PEER
|
SSL_VERIFY_FAIL_IF_NO_PEER_CERT
,
NULL
);
// Certificate generation script is at
// https://github.com/cesanta/net_skeleton/blob/master/scripts/gen_certs.sh
static
int
ns_use_ca_cert
(
SSL_CTX
*
ctx
,
const
char
*
cert
)
{
if
(
ctx
==
NULL
)
{
return
-
1
;
}
else
if
(
cert
==
NULL
||
cert
[
0
]
==
'\0'
)
{
return
0
;
}
#endif
return
server
!=
NULL
&&
cert
==
NULL
?
0
:
-
1
;
SSL_CTX_set_verify
(
ctx
,
SSL_VERIFY_PEER
|
SSL_VERIFY_FAIL_IF_NO_PEER_CERT
,
0
);
return
SSL_CTX_load_verify_locations
(
ctx
,
cert
,
NULL
)
==
1
?
0
:
-
2
;
}
int
ns_set_ssl_cert
(
struct
ns_server
*
server
,
const
char
*
cert
)
{
#ifdef NS_ENABLE_SSL
if
(
cert
!=
NULL
&&
(
server
->
ssl_ctx
=
SSL_CTX_new
(
SSLv23_server_method
()))
==
NULL
)
{
static
int
ns_use_cert
(
SSL_CTX
*
ctx
,
const
char
*
pem_file
)
{
if
(
ctx
==
NULL
)
{
return
-
1
;
}
else
if
(
SSL_CTX_use_certificate_file
(
server
->
ssl_ctx
,
cert
,
1
)
==
0
||
SSL_CTX_use_PrivateKey_file
(
server
->
ssl_ctx
,
cert
,
1
)
==
0
)
{
}
else
if
(
pem_file
==
NULL
||
pem_file
[
0
]
==
'\0'
)
{
return
0
;
}
else
if
(
SSL_CTX_use_certificate_file
(
ctx
,
pem_file
,
1
)
==
0
||
SSL_CTX_use_PrivateKey_file
(
ctx
,
pem_file
,
1
)
==
0
)
{
return
-
2
;
}
else
{
SSL_CTX_set_mode
(
server
->
ssl_
ctx
,
SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER
);
SSL_CTX_use_certificate_chain_file
(
server
->
ssl_ctx
,
cert
);
SSL_CTX_set_mode
(
ctx
,
SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER
);
SSL_CTX_use_certificate_chain_file
(
ctx
,
pem_file
);
return
0
;
}
#endif
return
server
!=
NULL
&&
cert
==
NULL
?
0
:
-
3
;
}
#endif // NS_ENABLE_SSL
int
ns_bind
(
struct
ns_server
*
server
,
const
char
*
str
)
{
struct
ns_connection
*
ns_bind
(
struct
ns_mgr
*
srv
,
const
char
*
str
,
void
*
data
)
{
union
socket_address
sa
;
ns_parse_port_string
(
str
,
&
sa
);
if
(
server
->
listening_sock
!=
INVALID_SOCKET
)
{
closesocket
(
server
->
listening_sock
);
struct
ns_connection
*
nc
=
NULL
;
int
use_ssl
,
proto
;
char
cert
[
100
],
ca_cert
[
100
];
sock_t
sock
;
ns_parse_address
(
str
,
&
sa
,
&
proto
,
&
use_ssl
,
cert
,
ca_cert
);
if
(
use_ssl
&&
cert
[
0
]
==
'\0'
)
return
NULL
;
if
((
sock
=
ns_open_listening_socket
(
&
sa
,
proto
))
==
INVALID_SOCKET
)
{
}
else
if
((
nc
=
ns_add_sock
(
srv
,
sock
,
NULL
))
==
NULL
)
{
closesocket
(
sock
);
}
else
{
nc
->
sa
=
sa
;
nc
->
flags
|=
NSF_LISTENING
;
nc
->
connection_data
=
data
;
if
(
proto
==
SOCK_DGRAM
)
{
nc
->
flags
|=
NSF_UDP
;
}
server
->
listening_sock
=
ns_open_listening_socket
(
&
sa
);
return
server
->
listening_sock
==
INVALID_SOCKET
?
-
1
:
(
int
)
ntohs
(
sa
.
sin
.
sin_port
);
}
#ifdef NS_ENABLE_SSL
if
(
use_ssl
)
{
nc
->
ssl_ctx
=
SSL_CTX_new
(
SSLv23_server_method
());
if
(
ns_use_cert
(
nc
->
ssl_ctx
,
cert
)
!=
0
||
ns_use_ca_cert
(
nc
->
ssl_ctx
,
ca_cert
)
!=
0
)
{
ns_close_conn
(
nc
);
nc
=
NULL
;
}
}
#endif
static
struct
ns_connection
*
accept_conn
(
struct
ns_server
*
server
)
{
DBG
((
"%p sock %d/%d ssl %p %p"
,
nc
,
sock
,
proto
,
nc
->
ssl_ctx
,
nc
->
ssl
));
}
return
nc
;
}
static
struct
ns_connection
*
accept_conn
(
struct
ns_connection
*
ls
)
{
struct
ns_connection
*
c
=
NULL
;
union
socket_address
sa
;
socklen_t
len
=
sizeof
(
sa
);
sock_t
sock
=
INVALID_SOCKET
;
// NOTE(lsm): on Windows, sock is always > FD_SETSIZE
if
((
sock
=
accept
(
server
->
listening_sock
,
&
sa
.
sa
,
&
len
))
==
INVALID_SOCKET
)
{
}
else
if
((
c
=
(
struct
ns_connection
*
)
NS_MALLOC
(
sizeof
(
*
c
)))
==
NULL
||
memset
(
c
,
0
,
sizeof
(
*
c
))
==
NULL
)
{
if
((
sock
=
accept
(
ls
->
sock
,
&
sa
.
sa
,
&
len
))
==
INVALID_SOCKET
)
{
}
else
if
((
c
=
ns_add_sock
(
ls
->
mgr
,
sock
,
NULL
))
==
NULL
)
{
closesocket
(
sock
);
#ifdef NS_ENABLE_SSL
}
else
if
(
server
->
ssl_ctx
!=
NULL
&&
((
c
->
ssl
=
SSL_new
(
server
->
ssl_ctx
))
==
NULL
||
}
else
if
(
ls
->
ssl_ctx
!=
NULL
&&
((
c
->
ssl
=
SSL_new
(
ls
->
ssl_ctx
))
==
NULL
||
SSL_set_fd
(
c
->
ssl
,
sock
)
!=
1
))
{
DBG
((
"SSL error"
));
closesocket
(
sock
);
free
(
c
);
ns_close_conn
(
c
);
c
=
NULL
;
#endif
}
else
{
ns_set_close_on_exec
(
sock
);
ns_set_non_blocking_mode
(
sock
);
c
->
server
=
server
;
c
->
sock
=
sock
;
c
->
flags
|=
NSF_ACCEPTED
;
ns_add_conn
(
server
,
c
);
c
->
listener
=
ls
;
ns_call
(
c
,
NS_ACCEPT
,
&
sa
);
DBG
((
"%p %d %p %p"
,
c
,
c
->
sock
,
c
->
ssl
,
server
->
ssl_ctx
));
DBG
((
"%p %d %p %p"
,
c
,
c
->
sock
,
c
->
ssl
_ctx
,
c
->
ssl
));
}
return
c
;
...
...
@@ -720,7 +801,7 @@ void ns_sock_to_str(sock_t sock, char *buf, size_t len, int flags) {
// Only Windoze Vista (and newer) have inet_ntop()
strncpy
(
buf
,
inet_ntoa
(
sa
.
sin
.
sin_addr
),
len
);
#else
inet_ntop
(
sa
.
sa
.
sa_family
,
(
void
*
)
&
sa
.
sin
.
sin_addr
,
buf
,
len
);
inet_ntop
(
sa
.
sa
.
sa_family
,
(
void
*
)
&
sa
.
sin
.
sin_addr
,
buf
,
(
socklen_t
)
len
);
#endif
}
if
(
flags
&
2
)
{
...
...
@@ -822,7 +903,7 @@ static void ns_read_from_socket(struct ns_connection *conn) {
}
else
#endif
{
while
((
n
=
recv
(
conn
->
sock
,
buf
,
sizeof
(
buf
),
0
))
>
0
)
{
while
((
n
=
(
int
)
recv
(
conn
->
sock
,
buf
,
sizeof
(
buf
),
0
))
>
0
)
{
DBG
((
"%p %d <- %d bytes (PLAIN)"
,
conn
,
conn
->
flags
,
n
));
iobuf_append
(
&
conn
->
recv_iobuf
,
buf
,
n
);
ns_call
(
conn
,
NS_RECV
,
&
n
);
...
...
@@ -851,7 +932,7 @@ static void ns_write_to_socket(struct ns_connection *conn) {
}
}
else
#endif
{
n
=
send
(
conn
->
sock
,
io
->
buf
,
io
->
len
,
0
);
}
{
n
=
(
int
)
send
(
conn
->
sock
,
io
->
buf
,
io
->
len
,
0
);
}
DBG
((
"%p %d -> %d bytes"
,
conn
,
conn
->
flags
,
n
));
...
...
@@ -864,7 +945,27 @@ static void ns_write_to_socket(struct ns_connection *conn) {
}
int
ns_send
(
struct
ns_connection
*
conn
,
const
void
*
buf
,
int
len
)
{
return
iobuf_append
(
&
conn
->
send_iobuf
,
buf
,
len
);
return
(
int
)
ns_out
(
conn
,
buf
,
len
);
}
static
void
ns_handle_udp
(
struct
ns_connection
*
ls
)
{
struct
ns_connection
nc
;
char
buf
[
NS_UDP_RECEIVE_BUFFER_SIZE
];
int
n
;
socklen_t
s_len
=
sizeof
(
nc
.
sa
);
memset
(
&
nc
,
0
,
sizeof
(
nc
));
n
=
recvfrom
(
ls
->
sock
,
buf
,
sizeof
(
buf
),
0
,
&
nc
.
sa
.
sa
,
&
s_len
);
if
(
n
<=
0
)
{
DBG
((
"%p recvfrom: %s"
,
ls
,
strerror
(
errno
)));
}
else
{
nc
.
recv_iobuf
.
buf
=
buf
;
nc
.
recv_iobuf
.
len
=
nc
.
recv_iobuf
.
size
=
n
;
nc
.
sock
=
ls
->
sock
;
nc
.
mgr
=
ls
->
mgr
;
DBG
((
"%p %d bytes received"
,
ls
,
n
));
ns_call
(
&
nc
,
NS_RECV
,
&
n
);
}
}
static
void
ns_add_to_set
(
sock_t
sock
,
fd_set
*
set
,
sock_t
*
max_fd
)
{
...
...
@@ -876,7 +977,7 @@ static void ns_add_to_set(sock_t sock, fd_set *set, sock_t *max_fd) {
}
}
int
ns_
server_poll
(
struct
ns_server
*
serve
r
,
int
milli
)
{
int
ns_
mgr_poll
(
struct
ns_mgr
*
mg
r
,
int
milli
)
{
struct
ns_connection
*
conn
,
*
tmp_conn
;
struct
timeval
tv
;
fd_set
read_set
,
write_set
;
...
...
@@ -884,15 +985,11 @@ int ns_server_poll(struct ns_server *server, int milli) {
sock_t
max_fd
=
INVALID_SOCKET
;
time_t
current_time
=
time
(
NULL
);
if
(
server
->
listening_sock
==
INVALID_SOCKET
&&
server
->
active_connections
==
NULL
)
return
0
;
FD_ZERO
(
&
read_set
);
FD_ZERO
(
&
write_set
);
ns_add_to_set
(
server
->
listening_sock
,
&
read_set
,
&
max_fd
);
ns_add_to_set
(
server
->
ctl
[
1
],
&
read_set
,
&
max_fd
);
ns_add_to_set
(
mgr
->
ctl
[
1
],
&
read_set
,
&
max_fd
);
for
(
conn
=
serve
r
->
active_connections
;
conn
!=
NULL
;
conn
=
tmp_conn
)
{
for
(
conn
=
mg
r
->
active_connections
;
conn
!=
NULL
;
conn
=
tmp_conn
)
{
tmp_conn
=
conn
->
next
;
ns_call
(
conn
,
NS_POLL
,
&
current_time
);
if
(
!
(
conn
->
flags
&
NSF_WANT_WRITE
))
{
...
...
@@ -918,34 +1015,38 @@ int ns_server_poll(struct ns_server *server, int milli) {
// now to prevent last_io_time being set to the past.
current_time
=
time
(
NULL
);
// Accept new connections
if
(
server
->
listening_sock
!=
INVALID_SOCKET
&&
FD_ISSET
(
server
->
listening_sock
,
&
read_set
))
{
// We're not looping here, and accepting just one connection at
// a time. The reason is that eCos does not respect non-blocking
// flag on a listening socket and hangs in a loop.
if
((
conn
=
accept_conn
(
server
))
!=
NULL
)
{
conn
->
last_io_time
=
current_time
;
}
}
// Read wakeup messages
if
(
serve
r
->
ctl
[
1
]
!=
INVALID_SOCKET
&&
FD_ISSET
(
serve
r
->
ctl
[
1
],
&
read_set
))
{
if
(
mg
r
->
ctl
[
1
]
!=
INVALID_SOCKET
&&
FD_ISSET
(
mg
r
->
ctl
[
1
],
&
read_set
))
{
struct
ctl_msg
ctl_msg
;
int
len
=
recv
(
serve
r
->
ctl
[
1
],
(
char
*
)
&
ctl_msg
,
sizeof
(
ctl_msg
),
0
);
send
(
serve
r
->
ctl
[
1
],
ctl_msg
.
message
,
1
,
0
);
int
len
=
(
int
)
recv
(
mg
r
->
ctl
[
1
],
(
char
*
)
&
ctl_msg
,
sizeof
(
ctl_msg
),
0
);
send
(
mg
r
->
ctl
[
1
],
ctl_msg
.
message
,
1
,
0
);
if
(
len
>=
(
int
)
sizeof
(
ctl_msg
.
callback
)
&&
ctl_msg
.
callback
!=
NULL
)
{
ns_iterate
(
server
,
ctl_msg
.
callback
,
ctl_msg
.
message
);
struct
ns_connection
*
c
;
for
(
c
=
ns_next
(
mgr
,
NULL
);
c
!=
NULL
;
c
=
ns_next
(
mgr
,
c
))
{
ctl_msg
.
callback
(
c
,
NS_POLL
,
ctl_msg
.
message
);
}
}
}
for
(
conn
=
serve
r
->
active_connections
;
conn
!=
NULL
;
conn
=
tmp_conn
)
{
for
(
conn
=
mg
r
->
active_connections
;
conn
!=
NULL
;
conn
=
tmp_conn
)
{
tmp_conn
=
conn
->
next
;
if
(
FD_ISSET
(
conn
->
sock
,
&
read_set
))
{
if
(
conn
->
flags
&
NSF_LISTENING
)
{
if
(
conn
->
flags
&
NSF_UDP
)
{
ns_handle_udp
(
conn
);
}
else
{
// We're not looping here, and accepting just one connection at
// a time. The reason is that eCos does not respect non-blocking
// flag on a listening socket and hangs in a loop.
accept_conn
(
conn
);
}
}
else
{
conn
->
last_io_time
=
current_time
;
ns_read_from_socket
(
conn
);
}
}
if
(
FD_ISSET
(
conn
->
sock
,
&
write_set
))
{
if
(
conn
->
flags
&
NSF_CONNECTING
)
{
ns_read_from_socket
(
conn
);
...
...
@@ -957,7 +1058,7 @@ int ns_server_poll(struct ns_server *server, int milli) {
}
}
for
(
conn
=
serve
r
->
active_connections
;
conn
!=
NULL
;
conn
=
tmp_conn
)
{
for
(
conn
=
mg
r
->
active_connections
;
conn
!=
NULL
;
conn
=
tmp_conn
)
{
tmp_conn
=
conn
->
next
;
num_active_connections
++
;
if
((
conn
->
flags
&
NSF_CLOSE_IMMEDIATELY
)
||
...
...
@@ -971,65 +1072,62 @@ int ns_server_poll(struct ns_server *server, int milli) {
return
num_active_connections
;
}
struct
ns_connection
*
ns_connect
(
struct
ns_
server
*
server
,
const
char
*
host
,
int
port
,
int
use_ssl
,
void
*
param
)
{
struct
ns_connection
*
ns_connect
(
struct
ns_
mgr
*
mgr
,
const
char
*
address
,
void
*
param
)
{
sock_t
sock
=
INVALID_SOCKET
;
struct
sockaddr_in
sin
;
struct
hostent
*
he
=
NULL
;
struct
ns_connection
*
conn
=
NULL
;
int
connect_ret_val
;
(
void
)
use_ssl
;
struct
ns_connection
*
nc
=
NULL
;
union
socket_address
sa
;
char
cert
[
100
],
ca_cert
[
100
];
int
connect_ret_val
,
use_ssl
,
proto
;
if
(
host
==
NULL
||
(
he
=
gethostbyname
(
host
))
==
NULL
||
(
sock
=
socket
(
AF_INET
,
SOCK_STREAM
,
0
))
==
INVALID_SOCKET
)
{
DBG
((
"gethostbyname(%s) failed: %s"
,
host
,
strerror
(
errno
)));
ns_parse_address
(
address
,
&
sa
,
&
proto
,
&
use_ssl
,
cert
,
ca_cert
);
if
((
sock
=
socket
(
AF_INET
,
proto
,
0
))
==
INVALID_SOCKET
)
{
return
NULL
;
}
sin
.
sin_family
=
AF_INET
;
sin
.
sin_port
=
htons
((
uint16_t
)
port
);
sin
.
sin_addr
=
*
(
struct
in_addr
*
)
he
->
h_addr_list
[
0
];
ns_set_non_blocking_mode
(
sock
);
connect_ret_val
=
connect
(
sock
,
&
sa
.
sa
,
sizeof
(
sa
.
sin
));
connect_ret_val
=
connect
(
sock
,
(
struct
sockaddr
*
)
&
sin
,
sizeof
(
sin
));
if
(
ns_is_error
(
connect_ret_val
))
{
if
(
connect_ret_val
!=
0
&&
ns_is_error
(
connect_ret_val
))
{
closesocket
(
sock
);
return
NULL
;
}
else
if
((
conn
=
(
struct
ns_connection
*
)
NS_MALLOC
(
sizeof
(
*
conn
)))
==
NULL
)
{
}
else
if
((
nc
=
ns_add_sock
(
mgr
,
sock
,
param
))
==
NULL
)
{
closesocket
(
sock
);
return
NULL
;
}
memset
(
conn
,
0
,
sizeof
(
*
conn
));
conn
->
server
=
server
;
conn
->
sock
=
sock
;
conn
->
connection_data
=
param
;
conn
->
flags
=
NSF_CONNECTING
;
conn
->
last_io_time
=
time
(
NULL
);
nc
->
sa
=
sa
;
// Essential, cause UDP conns will use sendto()
if
(
proto
==
SOCK_DGRAM
)
{
nc
->
flags
=
NSF_UDP
;
}
else
{
nc
->
flags
=
NSF_CONNECTING
;
}
#ifdef NS_ENABLE_SSL
if
(
use_ssl
&&
(
conn
->
ssl
=
SSL_new
(
server
->
client_ssl_ctx
))
!=
NULL
)
{
SSL_set_fd
(
conn
->
ssl
,
sock
);
if
(
use_ssl
)
{
if
((
nc
->
ssl_ctx
=
SSL_CTX_new
(
SSLv23_client_method
()))
==
NULL
||
ns_use_cert
(
nc
->
ssl_ctx
,
cert
)
!=
0
||
ns_use_ca_cert
(
nc
->
ssl_ctx
,
ca_cert
)
!=
0
||
(
nc
->
ssl
=
SSL_new
(
nc
->
ssl_ctx
))
==
NULL
)
{
ns_close_conn
(
nc
);
return
NULL
;
}
else
{
SSL_set_fd
(
nc
->
ssl
,
sock
);
}
}
#endif
ns_add_conn
(
server
,
conn
);
DBG
((
"%p %s:%d %d %p"
,
conn
,
host
,
port
,
conn
->
sock
,
conn
->
ssl
));
return
conn
;
return
nc
;
}
struct
ns_connection
*
ns_add_sock
(
struct
ns_
serve
r
*
s
,
sock_t
sock
,
void
*
p
)
{
struct
ns_connection
*
ns_add_sock
(
struct
ns_
mg
r
*
s
,
sock_t
sock
,
void
*
p
)
{
struct
ns_connection
*
conn
;
if
((
conn
=
(
struct
ns_connection
*
)
NS_MALLOC
(
sizeof
(
*
conn
)))
!=
NULL
)
{
memset
(
conn
,
0
,
sizeof
(
*
conn
));
ns_set_non_blocking_mode
(
sock
);
ns_set_close_on_exec
(
sock
);
conn
->
sock
=
sock
;
conn
->
connection_data
=
p
;
conn
->
serve
r
=
s
;
conn
->
mg
r
=
s
;
conn
->
last_io_time
=
time
(
NULL
);
ns_add_conn
(
s
,
conn
);
DBG
((
"%p %d"
,
conn
,
sock
));
...
...
@@ -1037,40 +1135,26 @@ struct ns_connection *ns_add_sock(struct ns_server *s, sock_t sock, void *p) {
return
conn
;
}
struct
ns_connection
*
ns_next
(
struct
ns_
serve
r
*
s
,
struct
ns_connection
*
conn
)
{
struct
ns_connection
*
ns_next
(
struct
ns_
mg
r
*
s
,
struct
ns_connection
*
conn
)
{
return
conn
==
NULL
?
s
->
active_connections
:
conn
->
next
;
}
void
ns_iterate
(
struct
ns_server
*
server
,
ns_callback_t
cb
,
void
*
param
)
{
struct
ns_connection
*
conn
,
*
tmp_conn
;
for
(
conn
=
server
->
active_connections
;
conn
!=
NULL
;
conn
=
tmp_conn
)
{
tmp_conn
=
conn
->
next
;
cb
(
conn
,
NS_POLL
,
param
);
}
}
void
ns_server_wakeup_ex
(
struct
ns_server
*
server
,
ns_callback_t
cb
,
void
*
data
,
size_t
len
)
{
void
ns_broadcast
(
struct
ns_mgr
*
mgr
,
ns_callback_t
cb
,
void
*
data
,
size_t
len
)
{
struct
ctl_msg
ctl_msg
;
if
(
serve
r
->
ctl
[
0
]
!=
INVALID_SOCKET
&&
data
!=
NULL
&&
if
(
mg
r
->
ctl
[
0
]
!=
INVALID_SOCKET
&&
data
!=
NULL
&&
len
<
sizeof
(
ctl_msg
.
message
))
{
ctl_msg
.
callback
=
cb
;
memcpy
(
ctl_msg
.
message
,
data
,
len
);
send
(
serve
r
->
ctl
[
0
],
(
char
*
)
&
ctl_msg
,
send
(
mg
r
->
ctl
[
0
],
(
char
*
)
&
ctl_msg
,
offsetof
(
struct
ctl_msg
,
message
)
+
len
,
0
);
recv
(
serve
r
->
ctl
[
0
],
(
char
*
)
&
len
,
1
,
0
);
recv
(
mg
r
->
ctl
[
0
],
(
char
*
)
&
len
,
1
,
0
);
}
}
void
ns_server_wakeup
(
struct
ns_server
*
server
)
{
ns_server_wakeup_ex
(
server
,
NULL
,
(
void
*
)
""
,
0
);
}
void
ns_server_init
(
struct
ns_server
*
s
,
void
*
server_data
,
ns_callback_t
cb
)
{
void
ns_mgr_init
(
struct
ns_mgr
*
s
,
void
*
user_data
,
ns_callback_t
cb
)
{
memset
(
s
,
0
,
sizeof
(
*
s
));
s
->
listening_sock
=
s
->
ctl
[
0
]
=
s
->
ctl
[
1
]
=
INVALID_SOCKET
;
s
->
server_data
=
serv
er_data
;
s
->
ctl
[
0
]
=
s
->
ctl
[
1
]
=
INVALID_SOCKET
;
s
->
user_data
=
us
er_data
;
s
->
callback
=
cb
;
#ifdef _WIN32
...
...
@@ -1089,33 +1173,25 @@ void ns_server_init(struct ns_server *s, void *server_data, ns_callback_t cb) {
#ifdef NS_ENABLE_SSL
{
static
int
init_done
;
if
(
!
init_done
)
{
SSL_library_init
();
init_done
++
;
}}
s
->
client_ssl_ctx
=
SSL_CTX_new
(
SSLv23_client_method
());
#endif
}
void
ns_
server_free
(
struct
ns_serve
r
*
s
)
{
void
ns_
mgr_free
(
struct
ns_mg
r
*
s
)
{
struct
ns_connection
*
conn
,
*
tmp_conn
;
DBG
((
"%p"
,
s
));
if
(
s
==
NULL
)
return
;
// Do one last poll, see https://github.com/cesanta/mongoose/issues/286
ns_
serve
r_poll
(
s
,
0
);
ns_
mg
r_poll
(
s
,
0
);
if
(
s
->
listening_sock
!=
INVALID_SOCKET
)
closesocket
(
s
->
listening_sock
);
if
(
s
->
ctl
[
0
]
!=
INVALID_SOCKET
)
closesocket
(
s
->
ctl
[
0
]);
if
(
s
->
ctl
[
1
]
!=
INVALID_SOCKET
)
closesocket
(
s
->
ctl
[
1
]);
s
->
listening_sock
=
s
->
ctl
[
0
]
=
s
->
ctl
[
1
]
=
INVALID_SOCKET
;
s
->
ctl
[
0
]
=
s
->
ctl
[
1
]
=
INVALID_SOCKET
;
for
(
conn
=
s
->
active_connections
;
conn
!=
NULL
;
conn
=
tmp_conn
)
{
tmp_conn
=
conn
->
next
;
ns_close_conn
(
conn
);
}
#ifdef NS_ENABLE_SSL
if
(
s
->
ssl_ctx
!=
NULL
)
SSL_CTX_free
(
s
->
ssl_ctx
);
if
(
s
->
client_ssl_ctx
!=
NULL
)
SSL_CTX_free
(
s
->
client_ssl_ctx
);
s
->
ssl_ctx
=
s
->
client_ssl_ctx
=
NULL
;
#endif
}
// net_skeleton end
#endif // NOEMBED_NET_SKELETON
...
...
@@ -1264,11 +1340,6 @@ enum {
#endif
#ifndef MONGOOSE_NO_SSI
SSI_PATTERN
,
#endif
#ifdef NS_ENABLE_SSL
SSL_CERTIFICATE
,
SSL_CA_CERTIFICATE
,
SSL_MITM_CERTS
,
#endif
URL_REWRITES
,
NUM_OPTIONS
...
...
@@ -1299,7 +1370,7 @@ static const char *static_config_options[] = {
#ifndef MONGOOSE_NO_FILESYSTEM
"hide_files_patterns"
,
NULL
,
"hexdump_file"
,
NULL
,
"index_files"
,
"index.html,index.htm,index.shtml,index.cgi,index.php
,index.lp
"
,
"index_files"
,
"index.html,index.htm,index.shtml,index.cgi,index.php"
,
#endif
"listening_port"
,
NULL
,
#ifndef _WIN32
...
...
@@ -1307,18 +1378,13 @@ static const char *static_config_options[] = {
#endif
#ifndef MONGOOSE_NO_SSI
"ssi_pattern"
,
"**.shtml$|**.shtm$"
,
#endif
#ifdef NS_ENABLE_SSL
"ssl_certificate"
,
NULL
,
"ssl_ca_certificate"
,
NULL
,
"ssl_mitm_certs"
,
NULL
,
#endif
"url_rewrites"
,
NULL
,
NULL
};
struct
mg_server
{
struct
ns_
server
ns_serve
r
;
struct
ns_
mgr
ns_mg
r
;
union
socket_address
lsa
;
// Listening socket address
mg_handler_t
event_handler
;
char
*
config_options
[
NUM_OPTIONS
];
...
...
@@ -1420,6 +1486,32 @@ void *mg_start_thread(void *(*f)(void *), void *p) {
}
#endif // MONGOOSE_NO_THREADS
#ifdef _WIN32
static
void
*
mmap
(
void
*
addr
,
int64_t
len
,
int
prot
,
int
flags
,
int
fd
,
int
offset
)
{
HANDLE
fh
=
(
HANDLE
)
_get_osfhandle
(
fd
);
HANDLE
mh
=
CreateFileMapping
(
fh
,
0
,
PAGE_READONLY
,
0
,
0
,
0
);
void
*
p
=
MapViewOfFile
(
mh
,
FILE_MAP_READ
,
0
,
0
,
(
size_t
)
len
);
CloseHandle
(
mh
);
return
p
;
}
#define munmap(x, y) UnmapViewOfFile(x)
#define MAP_FAILED NULL
#define MAP_PRIVATE 0
#define PROT_READ 0
#else
#include <sys/mman.h>
#endif
void
*
mg_mmap
(
FILE
*
fp
,
size_t
size
)
{
void
*
p
=
mmap
(
NULL
,
size
,
PROT_READ
,
MAP_PRIVATE
,
fileno
(
fp
),
0
);
return
p
==
MAP_FAILED
?
NULL
:
p
;
}
void
mg_munmap
(
void
*
p
,
size_t
size
)
{
munmap
(
p
,
size
);
}
#if defined(_WIN32) && !defined(MONGOOSE_NO_FILESYSTEM)
// Encode 'path' which is assumed UTF-8 string, into UNICODE string.
// wbuf and wbuf_len is a target buffer and its length.
...
...
@@ -2093,7 +2185,7 @@ static void open_cgi_endpoint(struct connection *conn, const char *prog) {
if
(
start_process
(
conn
->
server
->
config_options
[
CGI_INTERPRETER
],
prog
,
blk
.
buf
,
blk
.
vars
,
dir
,
fds
[
1
])
!=
0
)
{
conn
->
endpoint_type
=
EP_CGI
;
conn
->
endpoint
.
nc
=
ns_add_sock
(
&
conn
->
server
->
ns_
serve
r
,
fds
[
0
],
conn
);
conn
->
endpoint
.
nc
=
ns_add_sock
(
&
conn
->
server
->
ns_
mg
r
,
fds
[
0
],
conn
);
conn
->
endpoint
.
nc
->
flags
|=
MG_CGI_CONN
;
ns_send
(
conn
->
ns_conn
,
cgi_status
,
sizeof
(
cgi_status
)
-
1
);
conn
->
mg_conn
.
status_code
=
200
;
...
...
@@ -4160,7 +4252,6 @@ int mg_terminate_ssl(struct mg_connection *c, const char *cert) {
SSL_CTX
*
ctx
;
DBG
((
"%p MITM"
,
conn
));
SSL_library_init
();
if
((
ctx
=
SSL_CTX_new
(
SSLv23_server_method
()))
==
NULL
)
return
0
;
SSL_CTX_use_certificate_file
(
ctx
,
cert
,
1
);
...
...
@@ -4170,7 +4261,7 @@ int mg_terminate_ssl(struct mg_connection *c, const char *cert) {
// When clear-text reply is pushed to client, switch to SSL mode.
// TODO(lsm): check for send() failure
send
(
conn
->
ns_conn
->
sock
,
ok
,
sizeof
(
ok
)
-
1
,
0
);
DBG
((
"%p %lu %d SEND"
,
c
,
(
unsigned
long
)
sizeof
(
ok
)
-
1
,
n
));
//DBG(("%p %lu %d SEND", c, (unsigned long)
sizeof(ok) - 1, n));
conn
->
ns_conn
->
send_iobuf
.
len
=
0
;
conn
->
endpoint_type
=
EP_USER
;
// To keep-alive in close_local_endpoint()
close_local_endpoint
(
conn
);
// Clean up current CONNECT request
...
...
@@ -4182,12 +4273,12 @@ int mg_terminate_ssl(struct mg_connection *c, const char *cert) {
}
#endif
int
mg_forward
(
struct
mg_connection
*
c
,
const
char
*
host
,
int
port
,
int
ssl
)
{
int
mg_forward
(
struct
mg_connection
*
c
,
const
char
*
addr
)
{
static
const
char
ok
[]
=
"HTTP/1.1 200 OK
\r\n\r\n
"
;
struct
connection
*
conn
=
MG_CONN_2_CONN
(
c
);
struct
ns_server
*
server
=
&
conn
->
server
->
ns_server
;
struct
ns_connection
*
pc
;
if
((
pc
=
ns_connect
(
server
,
host
,
port
,
ssl
,
conn
))
==
NULL
)
{
if
((
pc
=
ns_connect
(
&
conn
->
server
->
ns_mgr
,
addr
,
conn
))
==
NULL
)
{
conn
->
ns_conn
->
flags
|=
NSF_CLOSE_IMMEDIATELY
;
return
0
;
}
...
...
@@ -4196,12 +4287,12 @@ int mg_forward(struct mg_connection *c, const char *host, int port, int ssl) {
pc
->
flags
|=
MG_PROXY_CONN
;
conn
->
endpoint_type
=
EP_PROXY
;
conn
->
endpoint
.
nc
=
pc
;
DBG
((
"%p [%s] [%s:%d] -> %p %p"
,
conn
,
c
->
uri
,
host
,
port
,
pc
,
conn
->
ns_conn
->
ssl
));
DBG
((
"%p [%s] [%s] -> %p %p"
,
conn
,
c
->
uri
,
addr
,
pc
,
conn
->
ns_conn
->
ssl
));
if
(
strcmp
(
c
->
request_method
,
"CONNECT"
)
==
0
)
{
// For CONNECT request, reply with 200 OK. Tunnel is established.
mg_printf
(
c
,
"%s"
,
"HTTP/1.1 200 OK
\r\n\r\n
"
);
// TODO(lsm): check for send() failure
(
void
)
send
(
conn
->
ns_conn
->
sock
,
ok
,
sizeof
(
ok
)
-
1
,
0
);
}
else
{
// Strip "http://host:port" part from the URI
if
(
memcmp
(
c
->
uri
,
"http://"
,
7
)
==
0
)
c
->
uri
+=
7
;
...
...
@@ -4212,7 +4303,7 @@ int mg_forward(struct mg_connection *c, const char *host, int port, int ssl) {
}
static
void
proxify_connection
(
struct
connection
*
conn
)
{
char
proto
[
10
],
host
[
500
],
cert
[
500
];
char
proto
[
10
],
host
[
500
],
cert
[
500
]
,
addr
[
1000
]
;
unsigned
short
port
=
80
;
struct
mg_connection
*
c
=
&
conn
->
mg_conn
;
int
n
=
0
;
...
...
@@ -4225,25 +4316,9 @@ static void proxify_connection(struct connection *conn) {
n
=
0
;
}
#ifdef NS_ENABLE_SSL
// Find out whether we should be in the MITM mode
{
const
char
*
certs
=
conn
->
server
->
config_options
[
SSL_MITM_CERTS
];
int
host_len
=
strlen
(
host
);
struct
vec
a
,
b
;
while
(
conn
->
ns_conn
->
ssl
==
NULL
&&
port
!=
80
&&
(
certs
=
next_option
(
certs
,
&
a
,
&
b
))
!=
NULL
)
{
if
(
a
.
len
!=
host_len
||
mg_strncasecmp
(
a
.
ptr
,
host
,
a
.
len
))
continue
;
snprintf
(
cert
,
sizeof
(
cert
),
"%.*s"
,
b
.
len
,
b
.
ptr
);
mg_terminate_ssl
(
&
conn
->
mg_conn
,
cert
);
return
;
}
}
#endif
if
(
n
>
0
&&
mg_forward
(
c
,
host
,
port
,
conn
->
ns_conn
->
ssl
!=
NULL
))
{
}
else
{
snprintf
(
addr
,
sizeof
(
addr
),
"%s://%s:%hu"
,
conn
->
ns_conn
->
ssl
!=
NULL
?
"ssl"
:
"tcp"
,
host
,
port
);
if
(
n
<=
0
||
!
mg_forward
(
c
,
addr
))
{
conn
->
ns_conn
->
flags
|=
NSF_CLOSE_IMMEDIATELY
;
}
}
...
...
@@ -4535,12 +4610,11 @@ static void process_response(struct connection *conn) {
}
}
struct
mg_connection
*
mg_connect
(
struct
mg_server
*
server
,
const
char
*
host
,
int
port
,
int
use_ssl
)
{
struct
mg_connection
*
mg_connect
(
struct
mg_server
*
server
,
const
char
*
addr
)
{
struct
ns_connection
*
nsconn
;
struct
connection
*
conn
;
nsconn
=
ns_connect
(
&
server
->
ns_
server
,
host
,
port
,
use_ssl
,
NULL
);
nsconn
=
ns_connect
(
&
server
->
ns_
mgr
,
addr
,
NULL
);
if
(
nsconn
==
NULL
)
return
0
;
if
((
conn
=
(
struct
connection
*
)
calloc
(
1
,
sizeof
(
*
conn
)))
==
NULL
)
{
...
...
@@ -4555,7 +4629,7 @@ struct mg_connection *mg_connect(struct mg_server *server, const char *host,
conn
->
server
=
server
;
conn
->
endpoint_type
=
EP_CLIENT
;
//conn->handler = handler;
conn
->
mg_conn
.
server_param
=
server
->
ns_
server
.
serv
er_data
;
conn
->
mg_conn
.
server_param
=
server
->
ns_
mgr
.
us
er_data
;
conn
->
ns_conn
->
flags
=
NSF_CONNECTING
;
return
&
conn
->
mg_conn
;
...
...
@@ -4684,7 +4758,7 @@ static void transfer_file_data(struct connection *conn) {
}
int
mg_poll_server
(
struct
mg_server
*
server
,
int
milliseconds
)
{
return
ns_
server_poll
(
&
server
->
ns_serve
r
,
milliseconds
);
return
ns_
mgr_poll
(
&
server
->
ns_mg
r
,
milliseconds
);
}
void
mg_destroy_server
(
struct
mg_server
**
server
)
{
...
...
@@ -4692,7 +4766,7 @@ void mg_destroy_server(struct mg_server **server) {
struct
mg_server
*
s
=
*
server
;
int
i
;
ns_
server_free
(
&
s
->
ns_serve
r
);
ns_
mgr_free
(
&
s
->
ns_mg
r
);
for
(
i
=
0
;
i
<
(
int
)
ARRAY_SIZE
(
s
->
config_options
);
i
++
)
{
free
(
s
->
config_options
[
i
]);
// It is OK to free(NULL)
}
...
...
@@ -4701,34 +4775,15 @@ void mg_destroy_server(struct mg_server **server) {
}
}
struct
mg_iterator
{
mg_handler_t
cb
;
void
*
param
;
};
static
void
iter
(
struct
ns_connection
*
nsconn
,
enum
ns_event
ev
,
void
*
param
)
{
if
(
ev
==
NS_POLL
)
{
struct
mg_iterator
*
it
=
(
struct
mg_iterator
*
)
param
;
struct
connection
*
c
=
(
struct
connection
*
)
nsconn
->
connection_data
;
if
(
c
!=
NULL
)
c
->
mg_conn
.
callback_param
=
it
->
param
;
it
->
cb
(
&
c
->
mg_conn
,
MG_POLL
);
}
}
struct
mg_connection
*
mg_next
(
struct
mg_server
*
s
,
struct
mg_connection
*
c
)
{
struct
connection
*
conn
=
MG_CONN_2_CONN
(
c
);
struct
ns_connection
*
nc
=
ns_next
(
&
s
->
ns_
serve
r
,
struct
ns_connection
*
nc
=
ns_next
(
&
s
->
ns_
mg
r
,
c
==
NULL
?
NULL
:
conn
->
ns_conn
);
return
nc
==
NULL
?
NULL
:
&
((
struct
connection
*
)
nc
->
connection_data
)
->
mg_conn
;
}
// Apply function to all active connections.
void
mg_iterate_over_connections
(
struct
mg_server
*
server
,
mg_handler_t
cb
,
void
*
param
)
{
struct
mg_iterator
it
=
{
cb
,
param
};
ns_iterate
(
&
server
->
ns_server
,
iter
,
&
it
);
if
(
nc
!=
NULL
&&
nc
->
connection_data
!=
NULL
)
{
return
&
((
struct
connection
*
)
nc
->
connection_data
)
->
mg_conn
;
}
else
{
return
NULL
;
}
}
static
int
get_var
(
const
char
*
data
,
size_t
data_len
,
const
char
*
name
,
...
...
@@ -4886,18 +4941,18 @@ const char *mg_set_option(struct mg_server *server, const char *name,
DBG
((
"%s [%s]"
,
name
,
*
v
));
if
(
ind
==
LISTENING_PORT
)
{
int
port
=
ns_bind
(
&
server
->
ns_server
,
value
);
if
(
port
<
0
)
{
struct
ns_connection
*
c
=
ns_bind
(
&
server
->
ns_mgr
,
value
,
NULL
);
if
(
c
==
NULL
)
{
error_msg
=
"Cannot bind to port"
;
}
else
{
char
buf
[
100
];
ns_sock_to_str
(
server
->
ns_server
.
listening_
sock
,
buf
,
sizeof
(
buf
),
2
);
ns_sock_to_str
(
c
->
sock
,
buf
,
sizeof
(
buf
),
2
);
free
(
*
v
);
*
v
=
mg_strdup
(
buf
);
}
#ifndef MONGOOSE_NO_FILESYSTEM
}
else
if
(
ind
==
HEXDUMP_FILE
)
{
server
->
ns_
serve
r
.
hexdump_file
=
*
v
;
server
->
ns_
mg
r
.
hexdump_file
=
*
v
;
#endif
#ifndef _WIN32
}
else
if
(
ind
==
RUN_AS_USER
)
{
...
...
@@ -4909,21 +4964,6 @@ const char *mg_set_option(struct mg_server *server, const char *name,
}
else
if
(
setuid
(
pw
->
pw_uid
)
!=
0
)
{
error_msg
=
"setuid() failed"
;
}
#endif
#ifdef NS_ENABLE_SSL
}
else
if
(
ind
==
SSL_CERTIFICATE
)
{
int
res
=
ns_set_ssl_cert
(
&
server
->
ns_server
,
value
);
if
(
res
==
-
2
)
{
error_msg
=
"Cannot load PEM"
;
}
else
if
(
res
==
-
3
)
{
error_msg
=
"SSL not enabled"
;
}
else
if
(
res
==
-
1
)
{
error_msg
=
"SSL_CTX_new() failed"
;
}
}
else
if
(
ind
==
SSL_CA_CERTIFICATE
)
{
if
(
ns_set_ssl_ca_cert
(
&
server
->
ns_server
,
value
)
!=
0
)
{
error_msg
=
"Error setting CA cert"
;
}
#endif
}
...
...
@@ -4943,7 +4983,7 @@ static void set_ips(struct ns_connection *nc, int is_rem) {
}
static
void
on_accept
(
struct
ns_connection
*
nc
,
union
socket_address
*
sa
)
{
struct
mg_server
*
server
=
(
struct
mg_server
*
)
nc
->
serve
r
;
struct
mg_server
*
server
=
(
struct
mg_server
*
)
nc
->
mg
r
;
struct
connection
*
conn
;
if
(
!
check_acl
(
server
->
config_options
[
ACCESS_CONTROL_LIST
],
...
...
@@ -4957,7 +4997,7 @@ static void on_accept(struct ns_connection *nc, union socket_address *sa) {
// Initialize the rest of connection attributes
conn
->
server
=
server
;
conn
->
mg_conn
.
server_param
=
nc
->
server
->
serv
er_data
;
conn
->
mg_conn
.
server_param
=
nc
->
mgr
->
us
er_data
;
set_ips
(
nc
,
1
);
set_ips
(
nc
,
0
);
}
...
...
@@ -5007,7 +5047,7 @@ static void mg_ev_handler(struct ns_connection *nc, enum ns_event ev, void *p) {
if
(
conn
!=
NULL
)
{
conn
->
num_bytes_recv
+=
*
(
int
*
)
p
;
}
if
(
nc
->
flags
&
NSF_ACCEPTED
)
{
if
(
nc
->
listener
!=
NULL
)
{
on_recv_data
(
conn
);
#ifndef MONGOOSE_NO_CGI
}
else
if
(
nc
->
flags
&
MG_CGI_CONN
)
{
...
...
@@ -5110,23 +5150,25 @@ void mg_wakeup_server_ex(struct mg_server *server, mg_handler_t cb,
va_end
(
ap
);
// "len + 1" is to include terminating \0 in the message
ns_
server_wakeup_ex
(
&
server
->
ns_serve
r
,
iter2
,
buf
,
len
+
1
);
ns_
broadcast
(
&
server
->
ns_mg
r
,
iter2
,
buf
,
len
+
1
);
}
void
mg_wakeup_server
(
struct
mg_server
*
server
)
{
ns_
server_wakeup_ex
(
&
server
->
ns_serve
r
,
NULL
,
(
void
*
)
""
,
0
);
ns_
broadcast
(
&
server
->
ns_mg
r
,
NULL
,
(
void
*
)
""
,
0
);
}
#if 0
void mg_set_listening_socket(struct mg_server *server, int sock) {
if
(
server
->
ns_
serve
r
.
listening_sock
!=
INVALID_SOCKET
)
{
closesocket
(
server
->
ns_
serve
r
.
listening_sock
);
if (server->ns_
mg
r.listening_sock != INVALID_SOCKET) {
closesocket(server->ns_
mg
r.listening_sock);
}
server
->
ns_
serve
r
.
listening_sock
=
(
sock_t
)
sock
;
server->ns_
mg
r.listening_sock = (sock_t) sock;
}
int mg_get_listening_socket(struct mg_server *server) {
return
server
->
ns_
serve
r
.
listening_sock
;
return server->ns_
mg
r.listening_sock;
}
#endif
const
char
*
mg_get_option
(
const
struct
mg_server
*
server
,
const
char
*
name
)
{
const
char
**
opts
=
(
const
char
**
)
server
->
config_options
;
...
...
@@ -5136,33 +5178,8 @@ const char *mg_get_option(const struct mg_server *server, const char *name) {
struct
mg_server
*
mg_create_server
(
void
*
server_data
,
mg_handler_t
handler
)
{
struct
mg_server
*
server
=
(
struct
mg_server
*
)
calloc
(
1
,
sizeof
(
*
server
));
ns_
server_init
(
&
server
->
ns_serve
r
,
server_data
,
mg_ev_handler
);
ns_
mgr_init
(
&
server
->
ns_mg
r
,
server_data
,
mg_ev_handler
);
set_default_option_values
(
server
->
config_options
);
server
->
event_handler
=
handler
;
return
server
;
}
#ifdef _WIN32
static
void
*
mmap
(
void
*
addr
,
int64_t
len
,
int
prot
,
int
flags
,
int
fd
,
int
offset
)
{
HANDLE
fh
=
(
HANDLE
)
_get_osfhandle
(
fd
);
HANDLE
mh
=
CreateFileMapping
(
fh
,
0
,
PAGE_READONLY
,
0
,
0
,
0
);
void
*
p
=
MapViewOfFile
(
mh
,
FILE_MAP_READ
,
0
,
0
,
(
size_t
)
len
);
CloseHandle
(
mh
);
return
p
;
}
#define munmap(x, y) UnmapViewOfFile(x)
#define MAP_FAILED NULL
#define MAP_PRIVATE 0
#define PROT_READ 0
#else
#include <sys/mman.h>
#endif
void
*
mg_mmap
(
FILE
*
fp
,
size_t
size
)
{
return
mmap
(
NULL
,
size
,
PROT_READ
,
MAP_PRIVATE
,
fileno
(
fp
),
0
);
}
void
mg_munmap
(
void
*
p
,
size_t
size
)
{
munmap
(
p
,
size
);
}
mongoose.h
View file @
6083b9c5
...
...
@@ -15,7 +15,7 @@
// Alternatively, you can license this library under a commercial
// license, as set out in <http://cesanta.com/>.
//
// $Date: 2014-09-0
1 19:53:26
UTC $
// $Date: 2014-09-0
9 17:07:55
UTC $
#ifndef MONGOOSE_HEADER_INCLUDED
#define MONGOOSE_HEADER_INCLUDED
...
...
@@ -55,7 +55,7 @@ struct mg_connection {
int
wsbits
;
// First byte of the websocket frame
void
*
server_param
;
// Parameter passed to mg_add_uri_handler()
void
*
connection_param
;
// Placeholder for connection-specific data
void
*
callback_param
;
// Needed by mg_iterate_over_connections()
void
*
callback_param
;
};
struct
mg_server
;
// Opaque structure describing server instance
...
...
@@ -95,11 +95,10 @@ const char **mg_get_valid_option_names(void);
const
char
*
mg_get_option
(
const
struct
mg_server
*
server
,
const
char
*
name
);
void
mg_set_listening_socket
(
struct
mg_server
*
,
int
sock
);
int
mg_get_listening_socket
(
struct
mg_server
*
);
void
mg_iterate_over_connections
(
struct
mg_server
*
,
mg_handler_t
,
void
*
);
struct
mg_connection
*
mg_next
(
struct
mg_server
*
,
struct
mg_connection
*
);
void
mg_wakeup_server
(
struct
mg_server
*
);
void
mg_wakeup_server_ex
(
struct
mg_server
*
,
mg_handler_t
,
const
char
*
,
...);
struct
mg_connection
*
mg_connect
(
struct
mg_server
*
,
const
char
*
,
int
,
int
);
struct
mg_connection
*
mg_connect
(
struct
mg_server
*
,
const
char
*
);
// Connection management functions
void
mg_send_status
(
struct
mg_connection
*
,
int
status_code
);
...
...
@@ -127,6 +126,7 @@ int mg_parse_multipart(const char *buf, int buf_len,
char
*
file_name
,
int
file_name_len
,
const
char
**
data
,
int
*
data_len
);
// Utility functions
void
*
mg_start_thread
(
void
*
(
*
func
)(
void
*
),
void
*
param
);
char
*
mg_md5
(
char
buf
[
33
],
...);
...
...
@@ -134,7 +134,7 @@ int mg_authorize_digest(struct mg_connection *c, FILE *fp);
int
mg_url_encode
(
const
char
*
src
,
size_t
s_len
,
char
*
dst
,
size_t
dst_len
);
int
mg_url_decode
(
const
char
*
src
,
int
src_len
,
char
*
dst
,
int
dst_len
,
int
);
int
mg_terminate_ssl
(
struct
mg_connection
*
c
,
const
char
*
cert
);
int
mg_forward
(
struct
mg_connection
*
,
const
char
*
host
,
int
port
,
int
use_ssl
);
int
mg_forward
(
struct
mg_connection
*
c
,
const
char
*
addr
);
void
*
mg_mmap
(
FILE
*
fp
,
size_t
size
);
void
mg_munmap
(
void
*
p
,
size_t
size
);
...
...
@@ -147,7 +147,6 @@ struct mg_expansion {
void
mg_template
(
struct
mg_connection
*
,
const
char
*
text
,
struct
mg_expansion
*
expansions
);
#ifdef __cplusplus
}
#endif // __cplusplus
...
...
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