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
Hide 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
// Copyright (c) 2004-2013 Sergey Lyubka
// Copyright (c) 2004-2013 Sergey Lyubka
// Copyright (c) 2013-2014 Cesanta Software Limited
// Copyright (c) 2013-2014 Cesanta Software Limited
//
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// furnished to do so, subject to the following conditions:
//
//
// The above copyright notice and this permission notice shall be included in
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// all copies or substantial portions of the Software.
//
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// THE SOFTWARE.
#undef UNICODE // Use ANSI WinAPI functions
#undef UNICODE // Use ANSI WinAPI functions
#undef _UNICODE // Use multibyte encoding on Windows
#undef _UNICODE // Use multibyte encoding on Windows
#define _MBCS // Use multibyte encoding on Windows
#define _MBCS // Use multibyte encoding on Windows
#define _WIN32_WINNT 0x500 // Enable MIIM_BITMAP
#define _WIN32_WINNT 0x500 // Enable MIIM_BITMAP
#define _CRT_SECURE_NO_WARNINGS // Disable deprecation warning in VS2005
#define _CRT_SECURE_NO_WARNINGS // Disable deprecation warning in VS2005
#define _XOPEN_SOURCE 600 // For PATH_MAX on linux
#define _XOPEN_SOURCE 600 // For PATH_MAX on linux
#undef WIN32_LEAN_AND_MEAN // Let windows.h always include winsock2.h
#undef WIN32_LEAN_AND_MEAN // Let windows.h always include winsock2.h
#include <sys/stat.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <signal.h>
#include <signal.h>
#include <string.h>
#include <string.h>
#include <errno.h>
#include <errno.h>
#include <limits.h>
#include <limits.h>
#include <stddef.h>
#include <stddef.h>
#include <stdarg.h>
#include <stdarg.h>
#include <ctype.h>
#include <ctype.h>
#include <time.h>
#include <time.h>
#include "mongoose.h"
#include "mongoose.h"
#ifdef _WIN32
#ifdef _WIN32
#include <windows.h>
#include <windows.h>
#include <direct.h> // For chdir()
#include <direct.h> // For chdir()
#include <winsvc.h>
#include <winsvc.h>
#include <shlobj.h>
#include <shlobj.h>
#ifndef PATH_MAX
#ifndef PATH_MAX
#define PATH_MAX MAX_PATH
#define PATH_MAX MAX_PATH
#endif
#endif
#ifndef S_ISDIR
#ifndef S_ISDIR
#define S_ISDIR(x) ((x) & _S_IFDIR)
#define S_ISDIR(x) ((x) & _S_IFDIR)
#endif
#endif
#define DIRSEP '\\'
#define DIRSEP '\\'
#define snprintf _snprintf
#define snprintf _snprintf
#define vsnprintf _vsnprintf
#define vsnprintf _vsnprintf
#define sleep(x) Sleep((x) * 1000)
#define sleep(x) Sleep((x) * 1000)
#define abs_path(rel, abs, abs_size) _fullpath((abs), (rel), (abs_size))
#define abs_path(rel, abs, abs_size) _fullpath((abs), (rel), (abs_size))
#define SIGCHLD 0
#define SIGCHLD 0
typedef
struct
_stat
file_stat_t
;
typedef
struct
_stat
file_stat_t
;
#define stat(x, y) _stat((x), (y))
#define stat(x, y) _stat((x), (y))
#else
#else
typedef
struct
stat
file_stat_t
;
typedef
struct
stat
file_stat_t
;
#include <sys/wait.h>
#include <sys/wait.h>
#include <unistd.h>
#include <unistd.h>
#ifdef IOS
#ifdef IOS
#include <ifaddrs.h>
#include <ifaddrs.h>
#endif
#endif
#define DIRSEP '/'
#define DIRSEP '/'
#define __cdecl
#define __cdecl
#define abs_path(rel, abs, abs_size) realpath((rel), (abs))
#define abs_path(rel, abs, abs_size) realpath((rel), (abs))
#endif // _WIN32
#endif // _WIN32
#define MAX_OPTIONS 100
#define MAX_OPTIONS 100
#define MAX_CONF_FILE_LINE_SIZE (8 * 1024)
#define MAX_CONF_FILE_LINE_SIZE (8 * 1024)
#ifndef MVER
#ifndef MVER
#define MVER MONGOOSE_VERSION
#define MVER MONGOOSE_VERSION
#endif
#endif
static
int
exit_flag
;
static
int
exit_flag
;
static
char
server_name
[
50
];
// Set by init_server_name()
static
char
server_name
[
50
];
// Set by init_server_name()
static
char
s_config_file
[
PATH_MAX
];
// Set by process_command_line_arguments
static
char
s_config_file
[
PATH_MAX
];
// Set by process_command_line_arguments
static
struct
mg_server
*
server
;
// Set by start_mongoose()
static
struct
mg_server
*
server
;
// Set by start_mongoose()
static
const
char
*
s_default_document_root
=
"."
;
static
const
char
*
s_default_document_root
=
"."
;
static
const
char
*
s_default_listening_port
=
"8080"
;
static
const
char
*
s_default_listening_port
=
"8080"
;
static
char
**
s_argv
=
{
NULL
};
static
char
**
s_argv
=
{
NULL
};
static
void
set_options
(
char
*
argv
[]);
static
void
set_options
(
char
*
argv
[]);
#if !defined(CONFIG_FILE)
#if !defined(CONFIG_FILE)
#define CONFIG_FILE "mongoose.conf"
#define CONFIG_FILE "mongoose.conf"
#endif
/* !CONFIG_FILE */
#endif
/* !CONFIG_FILE */
static
void
__cdecl
signal_handler
(
int
sig_num
)
{
static
void
__cdecl
signal_handler
(
int
sig_num
)
{
// Reinstantiate signal handler
// Reinstantiate signal handler
signal
(
sig_num
,
signal_handler
);
signal
(
sig_num
,
signal_handler
);
#ifndef _WIN32
#ifndef _WIN32
// Do not do the trick with ignoring SIGCHLD, cause not all OSes (e.g. QNX)
// Do not do the trick with ignoring SIGCHLD, cause not all OSes (e.g. QNX)
// reap zombies if SIGCHLD is ignored. On QNX, for example, waitpid()
// reap zombies if SIGCHLD is ignored. On QNX, for example, waitpid()
// fails if SIGCHLD is ignored, making system() non-functional.
// fails if SIGCHLD is ignored, making system() non-functional.
if
(
sig_num
==
SIGCHLD
)
{
if
(
sig_num
==
SIGCHLD
)
{
do
{}
while
(
waitpid
(
-
1
,
&
sig_num
,
WNOHANG
)
>
0
);
do
{}
while
(
waitpid
(
-
1
,
&
sig_num
,
WNOHANG
)
>
0
);
}
else
}
else
#endif
#endif
{
exit_flag
=
sig_num
;
}
{
exit_flag
=
sig_num
;
}
}
}
static
void
vnotify
(
const
char
*
fmt
,
va_list
ap
,
int
must_exit
)
{
static
void
vnotify
(
const
char
*
fmt
,
va_list
ap
,
int
must_exit
)
{
char
msg
[
200
];
char
msg
[
200
];
vsnprintf
(
msg
,
sizeof
(
msg
),
fmt
,
ap
);
vsnprintf
(
msg
,
sizeof
(
msg
),
fmt
,
ap
);
fprintf
(
stderr
,
"%s
\n
"
,
msg
);
fprintf
(
stderr
,
"%s
\n
"
,
msg
);
if
(
must_exit
)
{
if
(
must_exit
)
{
exit
(
EXIT_FAILURE
);
exit
(
EXIT_FAILURE
);
}
}
}
}
static
void
notify
(
const
char
*
fmt
,
...)
{
static
void
notify
(
const
char
*
fmt
,
...)
{
va_list
ap
;
va_list
ap
;
va_start
(
ap
,
fmt
);
va_start
(
ap
,
fmt
);
vnotify
(
fmt
,
ap
,
0
);
vnotify
(
fmt
,
ap
,
0
);
va_end
(
ap
);
va_end
(
ap
);
}
}
static
void
die
(
const
char
*
fmt
,
...)
{
static
void
die
(
const
char
*
fmt
,
...)
{
va_list
ap
;
va_list
ap
;
va_start
(
ap
,
fmt
);
va_start
(
ap
,
fmt
);
vnotify
(
fmt
,
ap
,
1
);
vnotify
(
fmt
,
ap
,
1
);
va_end
(
ap
);
va_end
(
ap
);
}
}
static
void
show_usage_and_exit
(
void
)
{
static
void
show_usage_and_exit
(
void
)
{
const
char
**
names
;
const
char
**
names
;
int
i
;
int
i
;
fprintf
(
stderr
,
"Mongoose version %s (c) Sergey Lyubka, built on %s
\n
"
,
fprintf
(
stderr
,
"Mongoose version %s (c) Sergey Lyubka, built on %s
\n
"
,
MVER
,
__DATE__
);
MVER
,
__DATE__
);
fprintf
(
stderr
,
"Usage:
\n
"
);
fprintf
(
stderr
,
"Usage:
\n
"
);
#if !defined(MONGOOSE_NO_AUTH) && !defined(MONGOOSE_NO_FILESYSTEM)
#if !defined(MONGOOSE_NO_AUTH) && !defined(MONGOOSE_NO_FILESYSTEM)
fprintf
(
stderr
,
" mongoose -A <htpasswd_file> <realm> <user> <passwd>
\n
"
);
fprintf
(
stderr
,
" mongoose -A <htpasswd_file> <realm> <user> <passwd>
\n
"
);
#endif
#endif
fprintf
(
stderr
,
" mongoose [config_file]
\n
"
);
fprintf
(
stderr
,
" mongoose [config_file]
\n
"
);
fprintf
(
stderr
,
" mongoose [-option value ...]
\n
"
);
fprintf
(
stderr
,
" mongoose [-option value ...]
\n
"
);
fprintf
(
stderr
,
"
\n
OPTIONS:
\n
"
);
fprintf
(
stderr
,
"
\n
OPTIONS:
\n
"
);
names
=
mg_get_valid_option_names
();
names
=
mg_get_valid_option_names
();
for
(
i
=
0
;
names
[
i
]
!=
NULL
;
i
+=
2
)
{
for
(
i
=
0
;
names
[
i
]
!=
NULL
;
i
+=
2
)
{
fprintf
(
stderr
,
" -%s %s
\n
"
,
fprintf
(
stderr
,
" -%s %s
\n
"
,
names
[
i
],
names
[
i
+
1
]
==
NULL
?
"<empty>"
:
names
[
i
+
1
]);
names
[
i
],
names
[
i
+
1
]
==
NULL
?
"<empty>"
:
names
[
i
+
1
]);
}
}
exit
(
EXIT_FAILURE
);
exit
(
EXIT_FAILURE
);
}
}
#define EV_HANDLER NULL
#define EV_HANDLER NULL
static
char
*
sdup
(
const
char
*
str
)
{
static
char
*
sdup
(
const
char
*
str
)
{
char
*
p
;
char
*
p
;
if
((
p
=
(
char
*
)
malloc
(
strlen
(
str
)
+
1
))
!=
NULL
)
{
if
((
p
=
(
char
*
)
malloc
(
strlen
(
str
)
+
1
))
!=
NULL
)
{
strcpy
(
p
,
str
);
strcpy
(
p
,
str
);
}
}
return
p
;
return
p
;
}
}
static
void
set_option
(
char
**
options
,
const
char
*
name
,
const
char
*
value
)
{
static
void
set_option
(
char
**
options
,
const
char
*
name
,
const
char
*
value
)
{
int
i
;
int
i
;
for
(
i
=
0
;
i
<
MAX_OPTIONS
-
3
;
i
++
)
{
for
(
i
=
0
;
i
<
MAX_OPTIONS
-
3
;
i
++
)
{
if
(
options
[
i
]
==
NULL
)
{
if
(
options
[
i
]
==
NULL
)
{
options
[
i
]
=
sdup
(
name
);
options
[
i
]
=
sdup
(
name
);
options
[
i
+
1
]
=
sdup
(
value
);
options
[
i
+
1
]
=
sdup
(
value
);
options
[
i
+
2
]
=
NULL
;
options
[
i
+
2
]
=
NULL
;
break
;
break
;
}
else
if
(
!
strcmp
(
options
[
i
],
name
))
{
}
else
if
(
!
strcmp
(
options
[
i
],
name
))
{
free
(
options
[
i
+
1
]);
free
(
options
[
i
+
1
]);
options
[
i
+
1
]
=
sdup
(
value
);
options
[
i
+
1
]
=
sdup
(
value
);
break
;
break
;
}
}
}
}
if
(
i
==
MAX_OPTIONS
-
3
)
{
if
(
i
==
MAX_OPTIONS
-
3
)
{
die
(
"%s"
,
"Too many options specified"
);
die
(
"%s"
,
"Too many options specified"
);
}
}
}
}
static
void
process_command_line_arguments
(
char
*
argv
[],
char
**
options
)
{
static
void
process_command_line_arguments
(
char
*
argv
[],
char
**
options
)
{
char
line
[
MAX_CONF_FILE_LINE_SIZE
],
opt
[
sizeof
(
line
)],
val
[
sizeof
(
line
)],
char
line
[
MAX_CONF_FILE_LINE_SIZE
],
opt
[
sizeof
(
line
)],
val
[
sizeof
(
line
)],
*
p
,
cpath
[
PATH_MAX
];
*
p
,
cpath
[
PATH_MAX
];
FILE
*
fp
=
NULL
;
FILE
*
fp
=
NULL
;
size_t
i
,
cmd_line_opts_start
=
1
,
line_no
=
0
;
size_t
i
,
cmd_line_opts_start
=
1
,
line_no
=
0
;
// Should we use a config file ?
// Should we use a config file ?
if
(
argv
[
1
]
!=
NULL
&&
argv
[
1
][
0
]
!=
'-'
)
{
if
(
argv
[
1
]
!=
NULL
&&
argv
[
1
][
0
]
!=
'-'
)
{
snprintf
(
cpath
,
sizeof
(
cpath
),
"%s"
,
argv
[
1
]);
snprintf
(
cpath
,
sizeof
(
cpath
),
"%s"
,
argv
[
1
]);
cmd_line_opts_start
=
2
;
cmd_line_opts_start
=
2
;
}
else
if
((
p
=
strrchr
(
argv
[
0
],
DIRSEP
))
==
NULL
)
{
}
else
if
((
p
=
strrchr
(
argv
[
0
],
DIRSEP
))
==
NULL
)
{
// No command line flags specified. Look where binary lives
// No command line flags specified. Look where binary lives
snprintf
(
cpath
,
sizeof
(
cpath
),
"%s"
,
CONFIG_FILE
);
snprintf
(
cpath
,
sizeof
(
cpath
),
"%s"
,
CONFIG_FILE
);
}
else
{
}
else
{
snprintf
(
cpath
,
sizeof
(
cpath
),
"%.*s%c%s"
,
snprintf
(
cpath
,
sizeof
(
cpath
),
"%.*s%c%s"
,
(
int
)
(
p
-
argv
[
0
]),
argv
[
0
],
DIRSEP
,
CONFIG_FILE
);
(
int
)
(
p
-
argv
[
0
]),
argv
[
0
],
DIRSEP
,
CONFIG_FILE
);
}
}
abs_path
(
cpath
,
s_config_file
,
sizeof
(
s_config_file
));
abs_path
(
cpath
,
s_config_file
,
sizeof
(
s_config_file
));
fp
=
fopen
(
s_config_file
,
"r"
);
fp
=
fopen
(
s_config_file
,
"r"
);
// If config file was set in command line and open failed, die
// If config file was set in command line and open failed, die
if
(
cmd_line_opts_start
==
2
&&
fp
==
NULL
)
{
if
(
cmd_line_opts_start
==
2
&&
fp
==
NULL
)
{
die
(
"Cannot open config file %s: %s"
,
s_config_file
,
strerror
(
errno
));
die
(
"Cannot open config file %s: %s"
,
s_config_file
,
strerror
(
errno
));
}
}
// Load config file settings first
// Load config file settings first
if
(
fp
!=
NULL
)
{
if
(
fp
!=
NULL
)
{
fprintf
(
stderr
,
"Loading config file %s
\n
"
,
s_config_file
);
fprintf
(
stderr
,
"Loading config file %s
\n
"
,
s_config_file
);
// Loop over the lines in config file
// Loop over the lines in config file
while
(
fgets
(
line
,
sizeof
(
line
),
fp
)
!=
NULL
)
{
while
(
fgets
(
line
,
sizeof
(
line
),
fp
)
!=
NULL
)
{
line_no
++
;
line_no
++
;
// Ignore empty lines and comments
// Ignore empty lines and comments
for
(
i
=
0
;
isspace
(
*
(
unsigned
char
*
)
&
line
[
i
]);
)
i
++
;
for
(
i
=
0
;
isspace
(
*
(
unsigned
char
*
)
&
line
[
i
]);
)
i
++
;
if
(
line
[
i
]
==
'#'
||
line
[
i
]
==
'\0'
)
{
if
(
line
[
i
]
==
'#'
||
line
[
i
]
==
'\0'
)
{
continue
;
continue
;
}
}
if
(
sscanf
(
line
,
"%s %[^
\r\n
#]"
,
opt
,
val
)
!=
2
)
{
if
(
sscanf
(
line
,
"%s %[^
\r\n
#]"
,
opt
,
val
)
!=
2
)
{
printf
(
"%s: line %d is invalid, ignoring it:
\n
%s"
,
printf
(
"%s: line %d is invalid, ignoring it:
\n
%s"
,
s_config_file
,
(
int
)
line_no
,
line
);
s_config_file
,
(
int
)
line_no
,
line
);
}
else
{
}
else
{
set_option
(
options
,
opt
,
val
);
set_option
(
options
,
opt
,
val
);
}
}
}
}
fclose
(
fp
);
fclose
(
fp
);
}
}
// If we're under MacOS and started by launchd, then the second
// If we're under MacOS and started by launchd, then the second
// argument is process serial number, -psn_.....
// argument is process serial number, -psn_.....
// In this case, don't process arguments at all.
// In this case, don't process arguments at all.
if
(
argv
[
1
]
==
NULL
||
memcmp
(
argv
[
1
],
"-psn_"
,
5
)
!=
0
)
{
if
(
argv
[
1
]
==
NULL
||
memcmp
(
argv
[
1
],
"-psn_"
,
5
)
!=
0
)
{
// Handle command line flags.
// Handle command line flags.
// They override config file and default settings.
// They override config file and default settings.
for
(
i
=
cmd_line_opts_start
;
argv
[
i
]
!=
NULL
;
i
+=
2
)
{
for
(
i
=
cmd_line_opts_start
;
argv
[
i
]
!=
NULL
;
i
+=
2
)
{
if
(
argv
[
i
][
0
]
!=
'-'
||
argv
[
i
+
1
]
==
NULL
)
{
if
(
argv
[
i
][
0
]
!=
'-'
||
argv
[
i
+
1
]
==
NULL
)
{
show_usage_and_exit
();
show_usage_and_exit
();
}
}
set_option
(
options
,
&
argv
[
i
][
1
],
argv
[
i
+
1
]);
set_option
(
options
,
&
argv
[
i
][
1
],
argv
[
i
+
1
]);
}
}
}
}
}
}
static
void
init_server_name
(
void
)
{
static
void
init_server_name
(
void
)
{
const
char
*
descr
=
""
;
const
char
*
descr
=
""
;
snprintf
(
server_name
,
sizeof
(
server_name
),
"Mongoose web server v.%s%s"
,
snprintf
(
server_name
,
sizeof
(
server_name
),
"Mongoose web server v.%s%s"
,
MVER
,
descr
);
MVER
,
descr
);
}
}
static
int
is_path_absolute
(
const
char
*
path
)
{
static
int
is_path_absolute
(
const
char
*
path
)
{
#ifdef _WIN32
#ifdef _WIN32
return
path
!=
NULL
&&
return
path
!=
NULL
&&
((
path
[
0
]
==
'\\'
&&
path
[
1
]
==
'\\'
)
||
// UNC path, e.g. \\server\dir
((
path
[
0
]
==
'\\'
&&
path
[
1
]
==
'\\'
)
||
// UNC path, e.g. \\server\dir
(
isalpha
(
path
[
0
])
&&
path
[
1
]
==
':'
&&
path
[
2
]
==
'\\'
));
// E.g. X:\dir
(
isalpha
(
path
[
0
])
&&
path
[
1
]
==
':'
&&
path
[
2
]
==
'\\'
));
// E.g. X:\dir
#else
#else
return
path
!=
NULL
&&
path
[
0
]
==
'/'
;
return
path
!=
NULL
&&
path
[
0
]
==
'/'
;
#endif
#endif
}
}
static
char
*
get_option
(
char
**
options
,
const
char
*
option_name
)
{
static
char
*
get_option
(
char
**
options
,
const
char
*
option_name
)
{
int
i
;
int
i
;
for
(
i
=
0
;
options
[
i
]
!=
NULL
;
i
++
)
for
(
i
=
0
;
options
[
i
]
!=
NULL
;
i
++
)
if
(
!
strcmp
(
options
[
i
],
option_name
))
if
(
!
strcmp
(
options
[
i
],
option_name
))
return
options
[
i
+
1
];
return
options
[
i
+
1
];
return
NULL
;
return
NULL
;
}
}
static
void
*
serving_thread_func
(
void
*
param
)
{
static
void
*
serving_thread_func
(
void
*
param
)
{
struct
mg_server
*
srv
=
(
struct
mg_server
*
)
param
;
struct
mg_server
*
srv
=
(
struct
mg_server
*
)
param
;
while
(
exit_flag
==
0
)
{
while
(
exit_flag
==
0
)
{
mg_poll_server
(
srv
,
1000
);
mg_poll_server
(
srv
,
1000
);
}
}
return
NULL
;
return
NULL
;
}
}
static
int
path_exists
(
const
char
*
path
,
int
is_dir
)
{
static
int
path_exists
(
const
char
*
path
,
int
is_dir
)
{
file_stat_t
st
;
file_stat_t
st
;
return
path
==
NULL
||
(
stat
(
path
,
&
st
)
==
0
&&
return
path
==
NULL
||
(
stat
(
path
,
&
st
)
==
0
&&
((
S_ISDIR
(
st
.
st_mode
)
?
1
:
0
)
==
is_dir
));
((
S_ISDIR
(
st
.
st_mode
)
?
1
:
0
)
==
is_dir
));
}
}
static
void
verify_existence
(
char
**
options
,
const
char
*
name
,
int
is_dir
)
{
static
void
verify_existence
(
char
**
options
,
const
char
*
name
,
int
is_dir
)
{
const
char
*
path
=
get_option
(
options
,
name
);
const
char
*
path
=
get_option
(
options
,
name
);
if
(
!
path_exists
(
path
,
is_dir
))
{
if
(
!
path_exists
(
path
,
is_dir
))
{
notify
(
"Invalid path for %s: [%s]: (%s). Make sure that path is either "
notify
(
"Invalid path for %s: [%s]: (%s). Make sure that path is either "
"absolute, or it is relative to mongoose executable."
,
"absolute, or it is relative to mongoose executable."
,
name
,
path
,
strerror
(
errno
));
name
,
path
,
strerror
(
errno
));
}
}
}
}
static
void
set_absolute_path
(
char
*
options
[],
const
char
*
option_name
)
{
static
void
set_absolute_path
(
char
*
options
[],
const
char
*
option_name
)
{
char
path
[
PATH_MAX
],
abs
[
PATH_MAX
],
*
option_value
;
char
path
[
PATH_MAX
],
abs
[
PATH_MAX
],
*
option_value
;
const
char
*
p
;
const
char
*
p
;
// Check whether option is already set
// Check whether option is already set
option_value
=
get_option
(
options
,
option_name
);
option_value
=
get_option
(
options
,
option_name
);
// If option is already set and it is an absolute path,
// If option is already set and it is an absolute path,
// leave it as it is -- it's already absolute.
// leave it as it is -- it's already absolute.
if
(
option_value
!=
NULL
&&
!
is_path_absolute
(
option_value
))
{
if
(
option_value
!=
NULL
&&
!
is_path_absolute
(
option_value
))
{
// Not absolute. Use the directory where mongoose executable lives
// Not absolute. Use the directory where mongoose executable lives
// be the relative directory for everything.
// be the relative directory for everything.
// Extract mongoose executable directory into path.
// Extract mongoose executable directory into path.
if
((
p
=
strrchr
(
s_config_file
,
DIRSEP
))
==
NULL
)
{
if
((
p
=
strrchr
(
s_config_file
,
DIRSEP
))
==
NULL
)
{
getcwd
(
path
,
sizeof
(
path
));
getcwd
(
path
,
sizeof
(
path
));
}
else
{
}
else
{
snprintf
(
path
,
sizeof
(
path
),
"%.*s"
,
(
int
)
(
p
-
s_config_file
),
snprintf
(
path
,
sizeof
(
path
),
"%.*s"
,
(
int
)
(
p
-
s_config_file
),
s_config_file
);
s_config_file
);
}
}
strncat
(
path
,
"/"
,
sizeof
(
path
)
-
1
);
strncat
(
path
,
"/"
,
sizeof
(
path
)
-
1
);
strncat
(
path
,
option_value
,
sizeof
(
path
)
-
1
);
strncat
(
path
,
option_value
,
sizeof
(
path
)
-
1
);
// Absolutize the path, and set the option
// Absolutize the path, and set the option
abs_path
(
path
,
abs
,
sizeof
(
abs
));
abs_path
(
path
,
abs
,
sizeof
(
abs
));
set_option
(
options
,
option_name
,
abs
);
set_option
(
options
,
option_name
,
abs
);
}
}
}
}
#if !defined(MONGOOSE_NO_AUTH) && !defined(MONGOOSE_NO_FILESYSTEM)
#if !defined(MONGOOSE_NO_AUTH) && !defined(MONGOOSE_NO_FILESYSTEM)
int
modify_passwords_file
(
const
char
*
fname
,
const
char
*
domain
,
int
modify_passwords_file
(
const
char
*
fname
,
const
char
*
domain
,
const
char
*
user
,
const
char
*
pass
)
{
const
char
*
user
,
const
char
*
pass
)
{
int
found
;
int
found
;
char
line
[
512
],
u
[
512
],
d
[
512
],
ha1
[
33
],
tmp
[
PATH_MAX
];
char
line
[
512
],
u
[
512
],
d
[
512
],
ha1
[
33
],
tmp
[
PATH_MAX
];
FILE
*
fp
,
*
fp2
;
FILE
*
fp
,
*
fp2
;
found
=
0
;
found
=
0
;
fp
=
fp2
=
NULL
;
fp
=
fp2
=
NULL
;
// Regard empty password as no password - remove user record.
// Regard empty password as no password - remove user record.
if
(
pass
!=
NULL
&&
pass
[
0
]
==
'\0'
)
{
if
(
pass
!=
NULL
&&
pass
[
0
]
==
'\0'
)
{
pass
=
NULL
;
pass
=
NULL
;
}
}
(
void
)
snprintf
(
tmp
,
sizeof
(
tmp
),
"%s.tmp"
,
fname
);
(
void
)
snprintf
(
tmp
,
sizeof
(
tmp
),
"%s.tmp"
,
fname
);
// Create the file if does not exist
// Create the file if does not exist
if
((
fp
=
fopen
(
fname
,
"a+"
))
!=
NULL
)
{
if
((
fp
=
fopen
(
fname
,
"a+"
))
!=
NULL
)
{
fclose
(
fp
);
fclose
(
fp
);
}
}
// Open the given file and temporary file
// Open the given file and temporary file
if
((
fp
=
fopen
(
fname
,
"r"
))
==
NULL
)
{
if
((
fp
=
fopen
(
fname
,
"r"
))
==
NULL
)
{
return
0
;
return
0
;
}
else
if
((
fp2
=
fopen
(
tmp
,
"w+"
))
==
NULL
)
{
}
else
if
((
fp2
=
fopen
(
tmp
,
"w+"
))
==
NULL
)
{
fclose
(
fp
);
fclose
(
fp
);
return
0
;
return
0
;
}
}
// Copy the stuff to temporary file
// Copy the stuff to temporary file
while
(
fgets
(
line
,
sizeof
(
line
),
fp
)
!=
NULL
)
{
while
(
fgets
(
line
,
sizeof
(
line
),
fp
)
!=
NULL
)
{
if
(
sscanf
(
line
,
"%[^:]:%[^:]:%*s"
,
u
,
d
)
!=
2
)
{
if
(
sscanf
(
line
,
"%[^:]:%[^:]:%*s"
,
u
,
d
)
!=
2
)
{
continue
;
continue
;
}
}
if
(
!
strcmp
(
u
,
user
)
&&
!
strcmp
(
d
,
domain
))
{
if
(
!
strcmp
(
u
,
user
)
&&
!
strcmp
(
d
,
domain
))
{
found
++
;
found
++
;
if
(
pass
!=
NULL
)
{
if
(
pass
!=
NULL
)
{
mg_md5
(
ha1
,
user
,
":"
,
domain
,
":"
,
pass
,
NULL
);
mg_md5
(
ha1
,
user
,
":"
,
domain
,
":"
,
pass
,
NULL
);
fprintf
(
fp2
,
"%s:%s:%s
\n
"
,
user
,
domain
,
ha1
);
fprintf
(
fp2
,
"%s:%s:%s
\n
"
,
user
,
domain
,
ha1
);
}
}
}
else
{
}
else
{
fprintf
(
fp2
,
"%s"
,
line
);
fprintf
(
fp2
,
"%s"
,
line
);
}
}
}
}
// If new user, just add it
// If new user, just add it
if
(
!
found
&&
pass
!=
NULL
)
{
if
(
!
found
&&
pass
!=
NULL
)
{
mg_md5
(
ha1
,
user
,
":"
,
domain
,
":"
,
pass
,
NULL
);
mg_md5
(
ha1
,
user
,
":"
,
domain
,
":"
,
pass
,
NULL
);
fprintf
(
fp2
,
"%s:%s:%s
\n
"
,
user
,
domain
,
ha1
);
fprintf
(
fp2
,
"%s:%s:%s
\n
"
,
user
,
domain
,
ha1
);
}
}
// Close files
// Close files
fclose
(
fp
);
fclose
(
fp
);
fclose
(
fp2
);
fclose
(
fp2
);
// Put the temp file in place of real file
// Put the temp file in place of real file
remove
(
fname
);
remove
(
fname
);
rename
(
tmp
,
fname
);
rename
(
tmp
,
fname
);
return
1
;
return
1
;
}
}
#endif
#endif
static
void
start_mongoose
(
int
argc
,
char
*
argv
[])
{
static
void
start_mongoose
(
int
argc
,
char
*
argv
[])
{
s_argv
=
argv
;
s_argv
=
argv
;
if
((
server
=
mg_create_server
(
NULL
,
EV_HANDLER
))
==
NULL
)
{
if
((
server
=
mg_create_server
(
NULL
,
EV_HANDLER
))
==
NULL
)
{
die
(
"%s"
,
"Failed to start Mongoose."
);
die
(
"%s"
,
"Failed to start Mongoose."
);
}
}
#if !defined(MONGOOSE_NO_AUTH) && !defined(MONGOOSE_NO_FILESYSTEM)
#if !defined(MONGOOSE_NO_AUTH) && !defined(MONGOOSE_NO_FILESYSTEM)
// Edit passwords file if -A option is specified
// Edit passwords file if -A option is specified
if
(
argc
>
1
&&
!
strcmp
(
argv
[
1
],
"-A"
))
{
if
(
argc
>
1
&&
!
strcmp
(
argv
[
1
],
"-A"
))
{
if
(
argc
!=
6
)
{
if
(
argc
!=
6
)
{
show_usage_and_exit
();
show_usage_and_exit
();
}
}
exit
(
modify_passwords_file
(
argv
[
2
],
argv
[
3
],
argv
[
4
],
argv
[
5
])
?
exit
(
modify_passwords_file
(
argv
[
2
],
argv
[
3
],
argv
[
4
],
argv
[
5
])
?
EXIT_SUCCESS
:
EXIT_FAILURE
);
EXIT_SUCCESS
:
EXIT_FAILURE
);
}
}
#endif
#endif
// Show usage if -h or --help options are specified
// Show usage if -h or --help options are specified
if
(
argc
==
2
&&
(
!
strcmp
(
argv
[
1
],
"-h"
)
||
!
strcmp
(
argv
[
1
],
"--help"
)))
{
if
(
argc
==
2
&&
(
!
strcmp
(
argv
[
1
],
"-h"
)
||
!
strcmp
(
argv
[
1
],
"--help"
)))
{
show_usage_and_exit
();
show_usage_and_exit
();
}
}
set_options
(
argv
);
set_options
(
argv
);
}
}
static
void
set_options
(
char
*
argv
[])
{
static
void
set_options
(
char
*
argv
[])
{
char
*
options
[
MAX_OPTIONS
];
char
*
options
[
MAX_OPTIONS
];
int
i
;
int
i
;
options
[
0
]
=
NULL
;
options
[
0
]
=
NULL
;
set_option
(
options
,
"document_root"
,
s_default_document_root
);
set_option
(
options
,
"document_root"
,
s_default_document_root
);
set_option
(
options
,
"listening_port"
,
s_default_listening_port
);
set_option
(
options
,
"listening_port"
,
s_default_listening_port
);
// Update config based on command line arguments
// Update config based on command line arguments
process_command_line_arguments
(
argv
,
options
);
process_command_line_arguments
(
argv
,
options
);
// Make sure we have absolute paths for files and directories
// Make sure we have absolute paths for files and directories
// https://github.com/valenok/mongoose/issues/181
// https://github.com/valenok/mongoose/issues/181
set_absolute_path
(
options
,
"document_root"
);
set_absolute_path
(
options
,
"document_root"
);
set_absolute_path
(
options
,
"dav_auth_file"
);
set_absolute_path
(
options
,
"dav_auth_file"
);
set_absolute_path
(
options
,
"cgi_interpreter"
);
set_absolute_path
(
options
,
"cgi_interpreter"
);
set_absolute_path
(
options
,
"access_log_file"
);
set_absolute_path
(
options
,
"access_log_file"
);
set_absolute_path
(
options
,
"global_auth_file"
);
set_absolute_path
(
options
,
"global_auth_file"
);
set_absolute_path
(
options
,
"ssl_certificate"
);
set_absolute_path
(
options
,
"ssl_certificate"
);
if
(
!
path_exists
(
get_option
(
options
,
"document_root"
),
1
))
{
if
(
!
path_exists
(
get_option
(
options
,
"document_root"
),
1
))
{
set_option
(
options
,
"document_root"
,
s_default_document_root
);
set_option
(
options
,
"document_root"
,
s_default_document_root
);
set_absolute_path
(
options
,
"document_root"
);
set_absolute_path
(
options
,
"document_root"
);
notify
(
"Setting document_root to [%s]"
,
notify
(
"Setting document_root to [%s]"
,
mg_get_option
(
server
,
"document_root"
));
mg_get_option
(
server
,
"document_root"
));
}
}
// Make extra verification for certain options
// Make extra verification for certain options
verify_existence
(
options
,
"document_root"
,
1
);
verify_existence
(
options
,
"document_root"
,
1
);
verify_existence
(
options
,
"cgi_interpreter"
,
0
);
verify_existence
(
options
,
"cgi_interpreter"
,
0
);
verify_existence
(
options
,
"ssl_certificate"
,
0
);
verify_existence
(
options
,
"ssl_certificate"
,
0
);
for
(
i
=
0
;
options
[
i
]
!=
NULL
;
i
+=
2
)
{
for
(
i
=
0
;
options
[
i
]
!=
NULL
;
i
+=
2
)
{
const
char
*
msg
=
mg_set_option
(
server
,
options
[
i
],
options
[
i
+
1
]);
const
char
*
msg
=
mg_set_option
(
server
,
options
[
i
],
options
[
i
+
1
]);
if
(
msg
!=
NULL
)
{
if
(
msg
!=
NULL
)
{
notify
(
"Failed to set option [%s] to [%s]: %s"
,
notify
(
"Failed to set option [%s] to [%s]: %s"
,
options
[
i
],
options
[
i
+
1
],
msg
);
options
[
i
],
options
[
i
+
1
],
msg
);
if
(
!
strcmp
(
options
[
i
],
"listening_port"
))
{
if
(
!
strcmp
(
options
[
i
],
"listening_port"
))
{
mg_set_option
(
server
,
"listening_port"
,
s_default_listening_port
);
mg_set_option
(
server
,
"listening_port"
,
s_default_listening_port
);
notify
(
"Setting %s to [%s]"
,
options
[
i
],
s_default_listening_port
);
notify
(
"Setting %s to [%s]"
,
options
[
i
],
s_default_listening_port
);
}
}
}
}
free
(
options
[
i
]);
free
(
options
[
i
]);
free
(
options
[
i
+
1
]);
free
(
options
[
i
+
1
]);
}
}
// Change current working directory to document root. This way,
// Change current working directory to document root. This way,
// scripts can use relative paths.
// scripts can use relative paths.
chdir
(
mg_get_option
(
server
,
"document_root"
));
chdir
(
mg_get_option
(
server
,
"document_root"
));
// Add an ability to pass listening socket to mongoose
#if 0
{
// Add an ability to pass listening socket to mongoose
const
char
*
env
=
getenv
(
"MONGOOSE_LISTENING_SOCKET"
);
{
if
(
env
!=
NULL
&&
atoi
(
env
)
>
0
)
{
const char *env = getenv("MONGOOSE_LISTENING_SOCKET");
mg_set_listening_socket
(
server
,
atoi
(
env
));
if (env != NULL && atoi(env) > 0 ) {
}
mg_set_listening_socket(server, atoi(env));
}
}
}
// Setup signal handler: quit on Ctrl-C
#endif
signal
(
SIGTERM
,
signal_handler
);
signal
(
SIGINT
,
signal_handler
);
// Setup signal handler: quit on Ctrl-C
#ifndef _WIN32
signal
(
SIGTERM
,
signal_handler
);
signal
(
SIGCHLD
,
signal_handler
);
signal
(
SIGINT
,
signal_handler
);
#endif
#ifndef _WIN32
}
signal
(
SIGCHLD
,
signal_handler
);
#endif
int
main
(
int
argc
,
char
*
argv
[])
{
}
init_server_name
();
start_mongoose
(
argc
,
argv
);
int
main
(
int
argc
,
char
*
argv
[])
{
printf
(
"%s serving [%s] on port %s
\n
"
,
init_server_name
();
server_name
,
mg_get_option
(
server
,
"document_root"
),
start_mongoose
(
argc
,
argv
);
mg_get_option
(
server
,
"listening_port"
));
printf
(
"%s serving [%s] on port %s
\n
"
,
fflush
(
stdout
);
// Needed, Windows terminals might not be line-buffered
server_name
,
mg_get_option
(
server
,
"document_root"
),
serving_thread_func
(
server
);
mg_get_option
(
server
,
"listening_port"
));
printf
(
"Exiting on signal %d ..."
,
exit_flag
);
fflush
(
stdout
);
// Needed, Windows terminals might not be line-buffered
fflush
(
stdout
);
serving_thread_func
(
server
);
mg_destroy_server
(
&
server
);
printf
(
"Exiting on signal %d ..."
,
exit_flag
);
printf
(
"%s
\n
"
,
" done."
);
fflush
(
stdout
);
mg_destroy_server
(
&
server
);
return
EXIT_SUCCESS
;
printf
(
"%s
\n
"
,
" done."
);
}
return
EXIT_SUCCESS
;
}
examples/unit_test.c
View file @
6083b9c5
...
@@ -396,9 +396,9 @@ static const char *test_server(void) {
...
@@ -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
,
"listening_port"
,
LISTENING_ADDR
)
==
NULL
);
ASSERT
(
mg_set_option
(
server
,
"document_root"
,
"."
)
==
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
;
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
;
conn
->
connection_param
=
buf2
;
{
int
i
;
for
(
i
=
0
;
i
<
50
;
i
++
)
mg_poll_server
(
server
,
1
);
}
{
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) {
...
@@ -483,7 +483,7 @@ static const char *test_mg_set_option(void) {
}
}
static
const
char
*
test_rewrites
(
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_server
*
server
=
mg_create_server
(
NULL
,
evh2
);
struct
mg_connection
*
conn
;
struct
mg_connection
*
conn
;
const
char
*
port
;
const
char
*
port
;
...
@@ -492,7 +492,8 @@ static const char *test_rewrites(void) {
...
@@ -492,7 +492,8 @@ static const char *test_rewrites(void) {
ASSERT
(
mg_set_option
(
server
,
"document_root"
,
"."
)
==
NULL
);
ASSERT
(
mg_set_option
(
server
,
"document_root"
,
"."
)
==
NULL
);
ASSERT
(
mg_set_option
(
server
,
"url_rewrites"
,
"/xx=unit_test.c"
)
==
NULL
);
ASSERT
(
mg_set_option
(
server
,
"url_rewrites"
,
"/xx=unit_test.c"
)
==
NULL
);
ASSERT
((
port
=
mg_get_option
(
server
,
"listening_port"
))
!=
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
;
conn
->
connection_param
=
buf1
;
{
int
i
;
for
(
i
=
0
;
i
<
50
;
i
++
)
mg_poll_server
(
server
,
1
);
}
{
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
// 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 <string.h>
#include <time.h>
#include <time.h>
...
...
examples/websocket_echo_server/websocket_echo_server.c
View file @
6083b9c5
// Copyright (c) 2013-2014 Cesanta Software Limited
// 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 <string.h>
#include <time.h>
#include <time.h>
...
...
examples/ws_ssl/Makefile
View file @
6083b9c5
# Copyright (c) 2014 Cesanta Software
# Copyright (c) 2014 Cesanta Software
# All rights reserved
# All rights reserved
CFLAGS
=
-W
-Wall
-I
../..
-g
-O0
$(CFLAGS_EXTRA)
CFLAGS
=
-W
-Wall
-I
../..
-I
.
-g
-O0
$(CFLAGS_EXTRA)
NS
=
../../../net_skeleton
SW
=
../../../ssl_wrapper
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
PROG
=
ws_ssl
all
:
$(PROG)
all
:
$(PROG)
$(PROG)
:
$(SOURCES)
$(PROG)
:
$(SOURCES)
$(CC)
-o
$(PROG)
$(SOURCES)
\
$(CC)
-o
$(PROG)
$(SOURCES)
\
-
I
$(NS)
-
DNS_ENABLE_SSL
-DNOEMBED_NET_SKELETON
\
-DNS_ENABLE_SSL
-DNOEMBED_NET_SKELETON
\
-
I
$(SW)
-
DSSL_WRAPPER_USE_AS_LIBRARY
-lssl
$(CFLAGS)
-DSSL_WRAPPER_USE_AS_LIBRARY
-lssl
$(CFLAGS)
clean
:
clean
:
rm
-rf
$(PROG)
*
.exe
*
.dSYM
*
.obj
*
.exp .
*
o
*
.lib
rm
-rf
$(PROG)
*
.exe
*
.dSYM
*
.obj
*
.exp .
*
o
*
.lib
examples/ws_ssl/net_skeleton.c
View file @
6083b9c5
...
@@ -14,7 +14,7 @@
...
@@ -14,7 +14,7 @@
// Alternatively, you can license this software under a commercial
// Alternatively, you can license this software under a commercial
// license, as set out in <http://cesanta.com/>.
// 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"
#include "net_skeleton.h"
...
...
examples/ws_ssl/net_skeleton.h
View file @
6083b9c5
...
@@ -14,7 +14,7 @@
...
@@ -14,7 +14,7 @@
// Alternatively, you can license this software under a commercial
// Alternatively, you can license this software under a commercial
// license, as set out in <http://cesanta.com/>.
// 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
#ifndef NS_SKELETON_HEADER_INCLUDED
#define NS_SKELETON_HEADER_INCLUDED
#define NS_SKELETON_HEADER_INCLUDED
...
...
examples/ws_ssl/ssl_wrapper.c
View file @
6083b9c5
...
@@ -14,7 +14,7 @@
...
@@ -14,7 +14,7 @@
// Alternatively, you can license this software under a commercial
// Alternatively, you can license this software under a commercial
// license, as set out in <http://cesanta.com/products.html>.
// 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 "net_skeleton.h"
#include "ssl_wrapper.h"
#include "ssl_wrapper.h"
...
...
examples/ws_ssl/ssl_wrapper.h
View file @
6083b9c5
...
@@ -14,7 +14,7 @@
...
@@ -14,7 +14,7 @@
// Alternatively, you can license this software under a commercial
// Alternatively, you can license this software under a commercial
// license, as set out in <http://cesanta.com/products.html>.
// 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
#ifndef SSL_WRAPPER_HEADER_INCLUDED
#define SSL_WRAPPER_HEADER_INCLUDED
#define SSL_WRAPPER_HEADER_INCLUDED
...
...
mongoose.c
View file @
6083b9c5
...
@@ -15,7 +15,7 @@
...
@@ -15,7 +15,7 @@
// Alternatively, you can license this library under a commercial
// Alternatively, you can license this library under a commercial
// license, as set out in <http://cesanta.com/>.
// 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
#ifdef NOEMBED_NET_SKELETON
#include "net_skeleton.h"
#include "net_skeleton.h"
...
@@ -36,11 +36,13 @@
...
@@ -36,11 +36,13 @@
//
//
// Alternatively, you can license this software under a commercial
// Alternatively, you can license this software under a commercial
// license, as set out in <http://cesanta.com/>.
// license, as set out in <http://cesanta.com/>.
//
// $Date: 2014-09-09 17:07:55 UTC $
#ifndef NS_SKELETON_HEADER_INCLUDED
#ifndef NS_SKELETON_HEADER_INCLUDED
#define 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 ANSI WinAPI functions
#undef _UNICODE // Use multibyte encoding on Windows
#undef _UNICODE // Use multibyte encoding on Windows
...
@@ -133,7 +135,9 @@ typedef int sock_t;
...
@@ -133,7 +135,9 @@ typedef int sock_t;
#define DBG(x)
#define DBG(x)
#endif
#endif
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
#endif
#ifdef NS_ENABLE_SSL
#ifdef NS_ENABLE_SSL
#ifdef __APPLE__
#ifdef __APPLE__
...
@@ -174,7 +178,7 @@ void iobuf_remove(struct iobuf *, size_t data_size);
...
@@ -174,7 +178,7 @@ void iobuf_remove(struct iobuf *, size_t data_size);
// Net skeleton interface
// Net skeleton interface
// Events. Meaning of event parameter (evp) is given in the comment.
// Events. Meaning of event parameter (evp) is given in the comment.
enum
ns_event
{
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_ACCEPT
,
// New connection accept()-ed. union socket_address *remote_addr
NS_CONNECT
,
// connect() succeeded or failed. int *success_status
NS_CONNECT
,
// connect() succeeded or failed. int *success_status
NS_RECV
,
// Data has benn received. int *num_bytes
NS_RECV
,
// Data has benn received. int *num_bytes
...
@@ -187,36 +191,37 @@ enum ns_event {
...
@@ -187,36 +191,37 @@ enum ns_event {
struct
ns_connection
;
struct
ns_connection
;
typedef
void
(
*
ns_callback_t
)(
struct
ns_connection
*
,
enum
ns_event
,
void
*
evp
);
typedef
void
(
*
ns_callback_t
)(
struct
ns_connection
*
,
enum
ns_event
,
void
*
evp
);
struct
ns_server
{
struct
ns_mgr
{
void
*
server_data
;
sock_t
listening_sock
;
struct
ns_connection
*
active_connections
;
struct
ns_connection
*
active_connections
;
ns_callback_t
callback
;
ns_callback_t
callback
;
// Event handler function
SSL_CTX
*
ssl_ctx
;
const
char
*
hexdump_file
;
// Debug hexdump file path
SSL_CTX
*
client_ssl_ctx
;
sock_t
ctl
[
2
];
// Socketpair for mg_wakeup()
const
char
*
hexdump_file
;
void
*
user_data
;
// User data
sock_t
ctl
[
2
];
};
};
struct
ns_connection
{
struct
ns_connection
{
struct
ns_connection
*
prev
,
*
next
;
struct
ns_connection
*
next
,
*
prev
;
// ns_mgr::active_connections linkage
struct
ns_server
*
server
;
struct
ns_connection
*
listener
;
// Set only for accept()-ed connections
struct
ns_mgr
*
mgr
;
sock_t
sock
;
sock_t
sock
;
union
socket_address
sa
;
union
socket_address
sa
;
struct
iobuf
recv_iobuf
;
struct
iobuf
recv_iobuf
;
struct
iobuf
send_iobuf
;
struct
iobuf
send_iobuf
;
SSL
*
ssl
;
SSL
*
ssl
;
SSL_CTX
*
ssl_ctx
;
void
*
connection_data
;
void
*
connection_data
;
time_t
last_io_time
;
time_t
last_io_time
;
unsigned
int
flags
;
unsigned
int
flags
;
#define NSF_FINISHED_SENDING_DATA (1 << 0)
#define NSF_FINISHED_SENDING_DATA (1 << 0)
#define NSF_BUFFER_BUT_DONT_SEND (1 << 1)
#define NSF_BUFFER_BUT_DONT_SEND (1 << 1)
#define NSF_SSL_HANDSHAKE_DONE (1 << 2)
#define NSF_SSL_HANDSHAKE_DONE (1 << 2)
#define NSF_CONNECTING (1 << 3)
#define NSF_CONNECTING (1 << 3)
#define NSF_CLOSE_IMMEDIATELY (1 << 4)
#define NSF_CLOSE_IMMEDIATELY (1 << 4)
#define NSF_ACCEPTED (1 << 5)
#define NSF_WANT_READ (1 << 5)
#define NSF_WANT_READ (1 << 6)
#define NSF_WANT_WRITE (1 << 6)
#define NSF_WANT_WRITE (1 << 7)
#define NSF_LISTENING (1 << 7)
#define NSF_UDP (1 << 8)
#define NSF_USER_1 (1 << 26)
#define NSF_USER_1 (1 << 26)
#define NSF_USER_2 (1 << 27)
#define NSF_USER_2 (1 << 27)
...
@@ -226,20 +231,15 @@ struct ns_connection {
...
@@ -226,20 +231,15 @@ struct ns_connection {
#define NSF_USER_6 (1 << 31)
#define NSF_USER_6 (1 << 31)
};
};
void
ns_server_init
(
struct
ns_server
*
,
void
*
server_data
,
ns_callback_t
);
void
ns_mgr_init
(
struct
ns_mgr
*
,
void
*
data
,
ns_callback_t
);
void
ns_server_free
(
struct
ns_server
*
);
void
ns_mgr_free
(
struct
ns_mgr
*
);
int
ns_server_poll
(
struct
ns_server
*
,
int
milli
);
int
ns_mgr_poll
(
struct
ns_mgr
*
,
int
milli
);
void
ns_server_wakeup
(
struct
ns_server
*
);
void
ns_broadcast
(
struct
ns_mgr
*
,
ns_callback_t
,
void
*
,
size_t
);
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_mgr
*
,
struct
ns_connection
*
);
struct
ns_connection
*
ns_next
(
struct
ns_server
*
,
struct
ns_connection
*
);
struct
ns_connection
*
ns_add_sock
(
struct
ns_mgr
*
,
sock_t
sock
,
void
*
p
);
struct
ns_connection
*
ns_add_sock
(
struct
ns_server
*
,
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_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
);
int
ns_send
(
struct
ns_connection
*
,
const
void
*
buf
,
int
len
);
int
ns_send
(
struct
ns_connection
*
,
const
void
*
buf
,
int
len
);
int
ns_printf
(
struct
ns_connection
*
,
const
char
*
fmt
,
...);
int
ns_printf
(
struct
ns_connection
*
,
const
char
*
fmt
,
...);
...
@@ -253,6 +253,7 @@ void ns_set_close_on_exec(sock_t);
...
@@ -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
);
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_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_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
#ifdef __cplusplus
}
}
...
@@ -274,6 +275,8 @@ int ns_avprintf(char **buf, size_t size, const char *fmt, va_list ap);
...
@@ -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
// Alternatively, you can license this software under a commercial
// license, as set out in <http://cesanta.com/>.
// license, as set out in <http://cesanta.com/>.
//
// $Date: 2014-09-09 17:07:55 UTC $
#ifndef NS_MALLOC
#ifndef NS_MALLOC
...
@@ -288,6 +291,9 @@ int ns_avprintf(char **buf, size_t size, const char *fmt, va_list ap);
...
@@ -288,6 +291,9 @@ int ns_avprintf(char **buf, size_t size, const char *fmt, va_list ap);
#define NS_FREE free
#define NS_FREE free
#endif
#endif
#define NS_UDP_RECEIVE_BUFFER_SIZE 2000
#define NS_VPRINTF_BUFFER_SIZE 500
struct
ctl_msg
{
struct
ctl_msg
{
ns_callback_t
callback
;
ns_callback_t
callback
;
char
message
[
1024
*
8
];
char
message
[
1024
*
8
];
...
@@ -338,6 +344,16 @@ void iobuf_remove(struct iobuf *io, size_t n) {
...
@@ -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
#ifndef NS_DISABLE_THREADS
void
*
ns_start_thread
(
void
*
(
*
f
)(
void
*
),
void
*
p
)
{
void
*
ns_start_thread
(
void
*
(
*
f
)(
void
*
),
void
*
p
)
{
#ifdef _WIN32
#ifdef _WIN32
...
@@ -361,15 +377,15 @@ void *ns_start_thread(void *(*f)(void *), void *p) {
...
@@ -361,15 +377,15 @@ void *ns_start_thread(void *(*f)(void *), void *p) {
}
}
#endif // NS_DISABLE_THREADS
#endif // NS_DISABLE_THREADS
static
void
ns_add_conn
(
struct
ns_
server
*
serve
r
,
struct
ns_connection
*
c
)
{
static
void
ns_add_conn
(
struct
ns_
mgr
*
mg
r
,
struct
ns_connection
*
c
)
{
c
->
next
=
serve
r
->
active_connections
;
c
->
next
=
mg
r
->
active_connections
;
serve
r
->
active_connections
=
c
;
mg
r
->
active_connections
=
c
;
c
->
prev
=
NULL
;
c
->
prev
=
NULL
;
if
(
c
->
next
!=
NULL
)
c
->
next
->
prev
=
c
;
if
(
c
->
next
!=
NULL
)
c
->
next
->
prev
=
c
;
}
}
static
void
ns_remove_conn
(
struct
ns_connection
*
conn
)
{
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
->
prev
)
conn
->
prev
->
next
=
conn
->
next
;
if
(
conn
->
next
)
conn
->
next
->
prev
=
conn
->
prev
;
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) {
...
@@ -412,12 +428,12 @@ int ns_avprintf(char **buf, size_t size, const char *fmt, va_list ap) {
return
len
;
return
len
;
}
}
int
ns_vprintf
(
struct
ns_connection
*
conn
,
const
char
*
fmt
,
va_list
ap
)
{
int
ns_vprintf
(
struct
ns_connection
*
nc
,
const
char
*
fmt
,
va_list
ap
)
{
char
mem
[
2000
],
*
buf
=
mem
;
char
mem
[
NS_VPRINTF_BUFFER_SIZE
],
*
buf
=
mem
;
int
len
;
int
len
;
if
((
len
=
ns_avprintf
(
&
buf
,
sizeof
(
mem
),
fmt
,
ap
))
>
0
)
{
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
)
{
if
(
buf
!=
mem
&&
buf
!=
NULL
)
{
free
(
buf
);
free
(
buf
);
...
@@ -450,7 +466,7 @@ static void hexdump(struct ns_connection *nc, const char *path,
...
@@ -450,7 +466,7 @@ static void hexdump(struct ns_connection *nc, const char *path,
ev
==
NS_RECV
?
"<-"
:
ev
==
NS_SEND
?
"->"
:
ev
==
NS_RECV
?
"<-"
:
ev
==
NS_SEND
?
"->"
:
ev
==
NS_ACCEPT
?
"<A"
:
ev
==
NS_CONNECT
?
"C>"
:
"XX"
,
ev
==
NS_ACCEPT
?
"<A"
:
ev
==
NS_CONNECT
?
"C>"
:
"XX"
,
dst
,
num_bytes
);
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
)
-
ns_hexdump
(
io
->
buf
+
(
ev
==
NS_SEND
?
0
:
io
->
len
)
-
(
ev
==
NS_SEND
?
0
:
num_bytes
),
num_bytes
,
buf
,
buf_size
);
(
ev
==
NS_SEND
?
0
:
num_bytes
),
num_bytes
,
buf
,
buf_size
);
fprintf
(
fp
,
"%s"
,
buf
);
fprintf
(
fp
,
"%s"
,
buf
);
...
@@ -461,17 +477,14 @@ static void hexdump(struct ns_connection *nc, const char *path,
...
@@ -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
)
{
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
;
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
)
{
static
void
ns_destroy_conn
(
struct
ns_connection
*
conn
)
{
DBG
((
"%p %d"
,
conn
,
conn
->
flags
));
ns_call
(
conn
,
NS_CLOSE
,
NULL
);
ns_remove_conn
(
conn
);
closesocket
(
conn
->
sock
);
closesocket
(
conn
->
sock
);
iobuf_free
(
&
conn
->
recv_iobuf
);
iobuf_free
(
&
conn
->
recv_iobuf
);
iobuf_free
(
&
conn
->
send_iobuf
);
iobuf_free
(
&
conn
->
send_iobuf
);
...
@@ -479,10 +492,20 @@ static void ns_close_conn(struct ns_connection *conn) {
...
@@ -479,10 +492,20 @@ static void ns_close_conn(struct ns_connection *conn) {
if
(
conn
->
ssl
!=
NULL
)
{
if
(
conn
->
ssl
!=
NULL
)
{
SSL_free
(
conn
->
ssl
);
SSL_free
(
conn
->
ssl
);
}
}
if
(
conn
->
ssl_ctx
!=
NULL
)
{
SSL_CTX_free
(
conn
->
ssl_ctx
);
}
#endif
#endif
NS_FREE
(
conn
);
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
)
{
void
ns_set_close_on_exec
(
sock_t
sock
)
{
#ifdef _WIN32
#ifdef _WIN32
(
void
)
SetHandleInformation
((
HANDLE
)
sock
,
HANDLE_FLAG_INHERIT
,
0
);
(
void
)
SetHandleInformation
((
HANDLE
)
sock
,
HANDLE_FLAG_INHERIT
,
0
);
...
@@ -543,10 +566,31 @@ int ns_socketpair(sock_t sp[2]) {
...
@@ -543,10 +566,31 @@ int ns_socketpair(sock_t sp[2]) {
}
}
#endif // NS_DISABLE_SOCKETPAIR
#endif // NS_DISABLE_SOCKETPAIR
// Valid listening port spec is: [ip_address:]port, e.g. "80", "127.0.0.1:3128"
// TODO(lsm): use non-blocking resolver
static
int
ns_parse_port_string
(
const
char
*
str
,
union
socket_address
*
sa
)
{
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
;
unsigned
int
a
,
b
,
c
,
d
,
port
;
int
len
=
0
;
int
n
=
0
,
len
=
0
;
char
host
[
200
];
#ifdef NS_ENABLE_IPV6
#ifdef NS_ENABLE_IPV6
char
buf
[
100
];
char
buf
[
100
];
#endif
#endif
...
@@ -557,36 +601,57 @@ static int ns_parse_port_string(const char *str, union socket_address *sa) {
...
@@ -557,36 +601,57 @@ static int ns_parse_port_string(const char *str, union socket_address *sa) {
memset
(
sa
,
0
,
sizeof
(
*
sa
));
memset
(
sa
,
0
,
sizeof
(
*
sa
));
sa
->
sin
.
sin_family
=
AF_INET
;
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
)
{
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
// 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_addr
.
s_addr
=
htonl
((
a
<<
24
)
|
(
b
<<
16
)
|
(
c
<<
8
)
|
d
);
sa
->
sin
.
sin_port
=
htons
((
uint16_t
)
port
);
sa
->
sin
.
sin_port
=
htons
((
uint16_t
)
port
);
#ifdef NS_ENABLE_IPV6
#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
))
{
inet_pton
(
AF_INET6
,
buf
,
&
sa
->
sin6
.
sin6_addr
))
{
// IPv6 address, e.g. [3ffe:2a00:100:7031::1]:8080
// IPv6 address, e.g. [3ffe:2a00:100:7031::1]:8080
sa
->
sin6
.
sin6_family
=
AF_INET6
;
sa
->
sin6
.
sin6_family
=
AF_INET6
;
sa
->
sin6
.
sin6_port
=
htons
((
uint16_t
)
port
);
sa
->
sin6
.
sin6_port
=
htons
((
uint16_t
)
port
);
#endif
#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
)
{
}
else
if
(
sscanf
(
str
,
"%u%n"
,
&
port
,
&
len
)
==
1
)
{
// If only port is specified, bind to IPv4, INADDR_ANY
// If only port is specified, bind to IPv4, INADDR_ANY
sa
->
sin
.
sin_port
=
htons
((
uint16_t
)
port
);
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
// 'sa' must be an initialized address to bind to
static
sock_t
ns_open_listening_socket
(
union
socket_address
*
sa
)
{
static
sock_t
ns_open_listening_socket
(
union
socket_address
*
sa
,
int
proto
)
{
socklen_t
len
=
sizeof
(
*
sa
);
socklen_t
sa_len
=
(
sa
->
sa
.
sa_family
==
AF_INET
)
?
sizeof
(
sa
->
sin
)
:
sizeof
(
sa
->
sin6
);
sock_t
sock
=
INVALID_SOCKET
;
sock_t
sock
=
INVALID_SOCKET
;
#ifndef _WIN32
#ifndef _WIN32
int
on
=
1
;
int
on
=
1
;
#endif
#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
#ifndef _WIN32
// SO_RESUSEADDR is not enabled on Windows because the semantics of
// SO_RESUSEADDR is not enabled on Windows because the semantics of
// SO_REUSEADDR on UNIX and Windows is different. On Windows,
// 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) {
...
@@ -596,12 +661,11 @@ static sock_t ns_open_listening_socket(union socket_address *sa) {
// scenarios. Therefore, SO_REUSEADDR was disabled on Windows.
// scenarios. Therefore, SO_REUSEADDR was disabled on Windows.
!
setsockopt
(
sock
,
SOL_SOCKET
,
SO_REUSEADDR
,
(
void
*
)
&
on
,
sizeof
(
on
))
&&
!
setsockopt
(
sock
,
SOL_SOCKET
,
SO_REUSEADDR
,
(
void
*
)
&
on
,
sizeof
(
on
))
&&
#endif
#endif
!
bind
(
sock
,
&
sa
->
sa
,
sa
->
sa
.
sa_family
==
AF_INET
?
!
bind
(
sock
,
&
sa
->
sa
,
sa_len
)
&&
sizeof
(
sa
->
sin
)
:
sizeof
(
sa
->
sin6
))
&&
(
proto
==
SOCK_DGRAM
||
listen
(
sock
,
SOMAXCONN
)
==
0
))
{
!
listen
(
sock
,
SOMAXCONN
))
{
ns_set_non_blocking_mode
(
sock
);
ns_set_non_blocking_mode
(
sock
);
// In case port was set to 0, get the real port number
// 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
)
{
}
else
if
(
sock
!=
INVALID_SOCKET
)
{
closesocket
(
sock
);
closesocket
(
sock
);
sock
=
INVALID_SOCKET
;
sock
=
INVALID_SOCKET
;
...
@@ -610,80 +674,97 @@ static sock_t ns_open_listening_socket(union socket_address *sa) {
...
@@ -610,80 +674,97 @@ static sock_t ns_open_listening_socket(union socket_address *sa) {
return
sock
;
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
#ifdef NS_ENABLE_SSL
STACK_OF
(
X509_NAME
)
*
list
=
SSL_load_client_CA_file
(
cert
);
// Certificate generation script is at
if
(
cert
!=
NULL
&&
server
->
ssl_ctx
!=
NULL
&&
list
!=
NULL
)
{
// https://github.com/cesanta/net_skeleton/blob/master/scripts/gen_certs.sh
SSL_CTX_set_client_CA_list
(
server
->
ssl_ctx
,
list
);
SSL_CTX_set_verify
(
server
->
ssl_ctx
,
SSL_VERIFY_PEER
|
static
int
ns_use_ca_cert
(
SSL_CTX
*
ctx
,
const
char
*
cert
)
{
SSL_VERIFY_FAIL_IF_NO_PEER_CERT
,
NULL
);
if
(
ctx
==
NULL
)
{
return
-
1
;
}
else
if
(
cert
==
NULL
||
cert
[
0
]
==
'\0'
)
{
return
0
;
return
0
;
}
}
#endif
SSL_CTX_set_verify
(
ctx
,
SSL_VERIFY_PEER
|
SSL_VERIFY_FAIL_IF_NO_PEER_CERT
,
0
);
return
server
!=
NULL
&&
cert
==
NULL
?
0
:
-
1
;
return
SSL_CTX_load_verify_locations
(
ctx
,
cert
,
NULL
)
==
1
?
0
:
-
2
;
}
}
int
ns_set_ssl_cert
(
struct
ns_server
*
server
,
const
char
*
cert
)
{
static
int
ns_use_cert
(
SSL_CTX
*
ctx
,
const
char
*
pem_file
)
{
#ifdef NS_ENABLE_SSL
if
(
ctx
==
NULL
)
{
if
(
cert
!=
NULL
&&
(
server
->
ssl_ctx
=
SSL_CTX_new
(
SSLv23_server_method
()))
==
NULL
)
{
return
-
1
;
return
-
1
;
}
else
if
(
SSL_CTX_use_certificate_file
(
server
->
ssl_ctx
,
cert
,
1
)
==
0
||
}
else
if
(
pem_file
==
NULL
||
pem_file
[
0
]
==
'\0'
)
{
SSL_CTX_use_PrivateKey_file
(
server
->
ssl_ctx
,
cert
,
1
)
==
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
;
return
-
2
;
}
else
{
}
else
{
SSL_CTX_set_mode
(
server
->
ssl_
ctx
,
SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER
);
SSL_CTX_set_mode
(
ctx
,
SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER
);
SSL_CTX_use_certificate_chain_file
(
server
->
ssl_ctx
,
cert
);
SSL_CTX_use_certificate_chain_file
(
ctx
,
pem_file
);
return
0
;
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
;
union
socket_address
sa
;
ns_parse_port_string
(
str
,
&
sa
);
struct
ns_connection
*
nc
=
NULL
;
if
(
server
->
listening_sock
!=
INVALID_SOCKET
)
{
int
use_ssl
,
proto
;
closesocket
(
server
->
listening_sock
);
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
;
}
#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
DBG
((
"%p sock %d/%d ssl %p %p"
,
nc
,
sock
,
proto
,
nc
->
ssl_ctx
,
nc
->
ssl
));
}
}
server
->
listening_sock
=
ns_open_listening_socket
(
&
sa
);
return
server
->
listening_sock
==
INVALID_SOCKET
?
-
1
:
(
int
)
ntohs
(
sa
.
sin
.
sin_port
);
}
return
nc
;
}
static
struct
ns_connection
*
accept_conn
(
struct
ns_
server
*
server
)
{
static
struct
ns_connection
*
accept_conn
(
struct
ns_
connection
*
ls
)
{
struct
ns_connection
*
c
=
NULL
;
struct
ns_connection
*
c
=
NULL
;
union
socket_address
sa
;
union
socket_address
sa
;
socklen_t
len
=
sizeof
(
sa
);
socklen_t
len
=
sizeof
(
sa
);
sock_t
sock
=
INVALID_SOCKET
;
sock_t
sock
=
INVALID_SOCKET
;
// NOTE(lsm): on Windows, sock is always > FD_SETSIZE
// NOTE(lsm): on Windows, sock is always > FD_SETSIZE
if
((
sock
=
accept
(
server
->
listening_sock
,
&
sa
.
sa
,
&
len
))
==
INVALID_SOCKET
)
{
if
((
sock
=
accept
(
ls
->
sock
,
&
sa
.
sa
,
&
len
))
==
INVALID_SOCKET
)
{
}
else
if
((
c
=
(
struct
ns_connection
*
)
NS_MALLOC
(
sizeof
(
*
c
)))
==
NULL
||
}
else
if
((
c
=
ns_add_sock
(
ls
->
mgr
,
sock
,
NULL
))
==
NULL
)
{
memset
(
c
,
0
,
sizeof
(
*
c
))
==
NULL
)
{
closesocket
(
sock
);
closesocket
(
sock
);
#ifdef NS_ENABLE_SSL
#ifdef NS_ENABLE_SSL
}
else
if
(
server
->
ssl_ctx
!=
NULL
&&
}
else
if
(
ls
->
ssl_ctx
!=
NULL
&&
((
c
->
ssl
=
SSL_new
(
server
->
ssl_ctx
))
==
NULL
||
((
c
->
ssl
=
SSL_new
(
ls
->
ssl_ctx
))
==
NULL
||
SSL_set_fd
(
c
->
ssl
,
sock
)
!=
1
))
{
SSL_set_fd
(
c
->
ssl
,
sock
)
!=
1
))
{
DBG
((
"SSL error"
));
DBG
((
"SSL error"
));
closesocket
(
sock
);
ns_close_conn
(
c
);
free
(
c
);
c
=
NULL
;
c
=
NULL
;
#endif
#endif
}
else
{
}
else
{
ns_set_close_on_exec
(
sock
);
c
->
listener
=
ls
;
ns_set_non_blocking_mode
(
sock
);
c
->
server
=
server
;
c
->
sock
=
sock
;
c
->
flags
|=
NSF_ACCEPTED
;
ns_add_conn
(
server
,
c
);
ns_call
(
c
,
NS_ACCEPT
,
&
sa
);
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
;
return
c
;
...
@@ -720,7 +801,7 @@ void ns_sock_to_str(sock_t sock, char *buf, size_t len, int flags) {
...
@@ -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()
// Only Windoze Vista (and newer) have inet_ntop()
strncpy
(
buf
,
inet_ntoa
(
sa
.
sin
.
sin_addr
),
len
);
strncpy
(
buf
,
inet_ntoa
(
sa
.
sin
.
sin_addr
),
len
);
#else
#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
#endif
}
}
if
(
flags
&
2
)
{
if
(
flags
&
2
)
{
...
@@ -822,7 +903,7 @@ static void ns_read_from_socket(struct ns_connection *conn) {
...
@@ -822,7 +903,7 @@ static void ns_read_from_socket(struct ns_connection *conn) {
}
else
}
else
#endif
#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
));
DBG
((
"%p %d <- %d bytes (PLAIN)"
,
conn
,
conn
->
flags
,
n
));
iobuf_append
(
&
conn
->
recv_iobuf
,
buf
,
n
);
iobuf_append
(
&
conn
->
recv_iobuf
,
buf
,
n
);
ns_call
(
conn
,
NS_RECV
,
&
n
);
ns_call
(
conn
,
NS_RECV
,
&
n
);
...
@@ -851,7 +932,7 @@ static void ns_write_to_socket(struct ns_connection *conn) {
...
@@ -851,7 +932,7 @@ static void ns_write_to_socket(struct ns_connection *conn) {
}
}
}
else
}
else
#endif
#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
));
DBG
((
"%p %d -> %d bytes"
,
conn
,
conn
->
flags
,
n
));
...
@@ -864,7 +945,27 @@ static void ns_write_to_socket(struct ns_connection *conn) {
...
@@ -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
)
{
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
)
{
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) {
...
@@ -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
ns_connection
*
conn
,
*
tmp_conn
;
struct
timeval
tv
;
struct
timeval
tv
;
fd_set
read_set
,
write_set
;
fd_set
read_set
,
write_set
;
...
@@ -884,15 +985,11 @@ int ns_server_poll(struct ns_server *server, int milli) {
...
@@ -884,15 +985,11 @@ int ns_server_poll(struct ns_server *server, int milli) {
sock_t
max_fd
=
INVALID_SOCKET
;
sock_t
max_fd
=
INVALID_SOCKET
;
time_t
current_time
=
time
(
NULL
);
time_t
current_time
=
time
(
NULL
);
if
(
server
->
listening_sock
==
INVALID_SOCKET
&&
server
->
active_connections
==
NULL
)
return
0
;
FD_ZERO
(
&
read_set
);
FD_ZERO
(
&
read_set
);
FD_ZERO
(
&
write_set
);
FD_ZERO
(
&
write_set
);
ns_add_to_set
(
server
->
listening_sock
,
&
read_set
,
&
max_fd
);
ns_add_to_set
(
mgr
->
ctl
[
1
],
&
read_set
,
&
max_fd
);
ns_add_to_set
(
server
->
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
;
tmp_conn
=
conn
->
next
;
ns_call
(
conn
,
NS_POLL
,
&
current_time
);
ns_call
(
conn
,
NS_POLL
,
&
current_time
);
if
(
!
(
conn
->
flags
&
NSF_WANT_WRITE
))
{
if
(
!
(
conn
->
flags
&
NSF_WANT_WRITE
))
{
...
@@ -918,34 +1015,38 @@ int ns_server_poll(struct ns_server *server, int milli) {
...
@@ -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.
// now to prevent last_io_time being set to the past.
current_time
=
time
(
NULL
);
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
// Read wakeup messages
if
(
serve
r
->
ctl
[
1
]
!=
INVALID_SOCKET
&&
if
(
mg
r
->
ctl
[
1
]
!=
INVALID_SOCKET
&&
FD_ISSET
(
serve
r
->
ctl
[
1
],
&
read_set
))
{
FD_ISSET
(
mg
r
->
ctl
[
1
],
&
read_set
))
{
struct
ctl_msg
ctl_msg
;
struct
ctl_msg
ctl_msg
;
int
len
=
recv
(
serve
r
->
ctl
[
1
],
(
char
*
)
&
ctl_msg
,
sizeof
(
ctl_msg
),
0
);
int
len
=
(
int
)
recv
(
mg
r
->
ctl
[
1
],
(
char
*
)
&
ctl_msg
,
sizeof
(
ctl_msg
),
0
);
send
(
serve
r
->
ctl
[
1
],
ctl_msg
.
message
,
1
,
0
);
send
(
mg
r
->
ctl
[
1
],
ctl_msg
.
message
,
1
,
0
);
if
(
len
>=
(
int
)
sizeof
(
ctl_msg
.
callback
)
&&
ctl_msg
.
callback
!=
NULL
)
{
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
;
tmp_conn
=
conn
->
next
;
if
(
FD_ISSET
(
conn
->
sock
,
&
read_set
))
{
if
(
FD_ISSET
(
conn
->
sock
,
&
read_set
))
{
conn
->
last_io_time
=
current_time
;
if
(
conn
->
flags
&
NSF_LISTENING
)
{
ns_read_from_socket
(
conn
);
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
(
FD_ISSET
(
conn
->
sock
,
&
write_set
))
{
if
(
conn
->
flags
&
NSF_CONNECTING
)
{
if
(
conn
->
flags
&
NSF_CONNECTING
)
{
ns_read_from_socket
(
conn
);
ns_read_from_socket
(
conn
);
...
@@ -957,7 +1058,7 @@ int ns_server_poll(struct ns_server *server, int milli) {
...
@@ -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
;
tmp_conn
=
conn
->
next
;
num_active_connections
++
;
num_active_connections
++
;
if
((
conn
->
flags
&
NSF_CLOSE_IMMEDIATELY
)
||
if
((
conn
->
flags
&
NSF_CLOSE_IMMEDIATELY
)
||
...
@@ -971,65 +1072,62 @@ int ns_server_poll(struct ns_server *server, int milli) {
...
@@ -971,65 +1072,62 @@ int ns_server_poll(struct ns_server *server, int milli) {
return
num_active_connections
;
return
num_active_connections
;
}
}
struct
ns_connection
*
ns_connect
(
struct
ns_
server
*
server
,
const
char
*
host
,
struct
ns_connection
*
ns_connect
(
struct
ns_
mgr
*
mgr
,
int
port
,
int
use_ssl
,
void
*
param
)
{
const
char
*
address
,
void
*
param
)
{
sock_t
sock
=
INVALID_SOCKET
;
sock_t
sock
=
INVALID_SOCKET
;
struct
sockaddr_in
sin
;
struct
ns_connection
*
nc
=
NULL
;
struct
hostent
*
he
=
NULL
;
union
socket_address
sa
;
struct
ns_connection
*
conn
=
NULL
;
char
cert
[
100
],
ca_cert
[
100
];
int
connect_ret_val
;
int
connect_ret_val
,
use_ssl
,
proto
;
(
void
)
use_ssl
;
if
(
host
==
NULL
||
(
he
=
gethostbyname
(
host
))
==
NULL
||
ns_parse_address
(
address
,
&
sa
,
&
proto
,
&
use_ssl
,
cert
,
ca_cert
);
(
sock
=
socket
(
AF_INET
,
SOCK_STREAM
,
0
))
==
INVALID_SOCKET
)
{
if
((
sock
=
socket
(
AF_INET
,
proto
,
0
))
==
INVALID_SOCKET
)
{
DBG
((
"gethostbyname(%s) failed: %s"
,
host
,
strerror
(
errno
)));
return
NULL
;
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
);
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
(
connect_ret_val
!=
0
&&
ns_is_error
(
connect_ret_val
))
{
if
(
ns_is_error
(
connect_ret_val
))
{
closesocket
(
sock
);
closesocket
(
sock
);
return
NULL
;
return
NULL
;
}
else
if
((
conn
=
(
struct
ns_connection
*
)
}
else
if
((
nc
=
ns_add_sock
(
mgr
,
sock
,
param
))
==
NULL
)
{
NS_MALLOC
(
sizeof
(
*
conn
)))
==
NULL
)
{
closesocket
(
sock
);
closesocket
(
sock
);
return
NULL
;
return
NULL
;
}
}
memset
(
conn
,
0
,
sizeof
(
*
conn
));
nc
->
sa
=
sa
;
// Essential, cause UDP conns will use sendto()
conn
->
server
=
server
;
if
(
proto
==
SOCK_DGRAM
)
{
conn
->
sock
=
sock
;
nc
->
flags
=
NSF_UDP
;
conn
->
connection_data
=
param
;
}
else
{
conn
->
flags
=
NSF_CONNECTING
;
nc
->
flags
=
NSF_CONNECTING
;
conn
->
last_io_time
=
time
(
NULL
);
}
#ifdef NS_ENABLE_SSL
#ifdef NS_ENABLE_SSL
if
(
use_ssl
&&
if
(
use_ssl
)
{
(
conn
->
ssl
=
SSL_new
(
server
->
client_ssl_ctx
))
!=
NULL
)
{
if
((
nc
->
ssl_ctx
=
SSL_CTX_new
(
SSLv23_client_method
()))
==
NULL
||
SSL_set_fd
(
conn
->
ssl
,
sock
);
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
#endif
ns_add_conn
(
server
,
conn
);
return
nc
;
DBG
((
"%p %s:%d %d %p"
,
conn
,
host
,
port
,
conn
->
sock
,
conn
->
ssl
));
return
conn
;
}
}
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
;
struct
ns_connection
*
conn
;
if
((
conn
=
(
struct
ns_connection
*
)
NS_MALLOC
(
sizeof
(
*
conn
)))
!=
NULL
)
{
if
((
conn
=
(
struct
ns_connection
*
)
NS_MALLOC
(
sizeof
(
*
conn
)))
!=
NULL
)
{
memset
(
conn
,
0
,
sizeof
(
*
conn
));
memset
(
conn
,
0
,
sizeof
(
*
conn
));
ns_set_non_blocking_mode
(
sock
);
ns_set_non_blocking_mode
(
sock
);
ns_set_close_on_exec
(
sock
);
conn
->
sock
=
sock
;
conn
->
sock
=
sock
;
conn
->
connection_data
=
p
;
conn
->
connection_data
=
p
;
conn
->
serve
r
=
s
;
conn
->
mg
r
=
s
;
conn
->
last_io_time
=
time
(
NULL
);
conn
->
last_io_time
=
time
(
NULL
);
ns_add_conn
(
s
,
conn
);
ns_add_conn
(
s
,
conn
);
DBG
((
"%p %d"
,
conn
,
sock
));
DBG
((
"%p %d"
,
conn
,
sock
));
...
@@ -1037,40 +1135,26 @@ struct ns_connection *ns_add_sock(struct ns_server *s, sock_t sock, void *p) {
...
@@ -1037,40 +1135,26 @@ struct ns_connection *ns_add_sock(struct ns_server *s, sock_t sock, void *p) {
return
conn
;
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
;
return
conn
==
NULL
?
s
->
active_connections
:
conn
->
next
;
}
}
void
ns_iterate
(
struct
ns_server
*
server
,
ns_callback_t
cb
,
void
*
param
)
{
void
ns_broadcast
(
struct
ns_mgr
*
mgr
,
ns_callback_t
cb
,
void
*
data
,
size_t
len
)
{
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
)
{
struct
ctl_msg
ctl_msg
;
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
))
{
len
<
sizeof
(
ctl_msg
.
message
))
{
ctl_msg
.
callback
=
cb
;
ctl_msg
.
callback
=
cb
;
memcpy
(
ctl_msg
.
message
,
data
,
len
);
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
);
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
)
{
void
ns_mgr_init
(
struct
ns_mgr
*
s
,
void
*
user_data
,
ns_callback_t
cb
)
{
ns_server_wakeup_ex
(
server
,
NULL
,
(
void
*
)
""
,
0
);
}
void
ns_server_init
(
struct
ns_server
*
s
,
void
*
server_data
,
ns_callback_t
cb
)
{
memset
(
s
,
0
,
sizeof
(
*
s
));
memset
(
s
,
0
,
sizeof
(
*
s
));
s
->
listening_sock
=
s
->
ctl
[
0
]
=
s
->
ctl
[
1
]
=
INVALID_SOCKET
;
s
->
ctl
[
0
]
=
s
->
ctl
[
1
]
=
INVALID_SOCKET
;
s
->
server_data
=
serv
er_data
;
s
->
user_data
=
us
er_data
;
s
->
callback
=
cb
;
s
->
callback
=
cb
;
#ifdef _WIN32
#ifdef _WIN32
...
@@ -1089,33 +1173,25 @@ void ns_server_init(struct ns_server *s, void *server_data, ns_callback_t cb) {
...
@@ -1089,33 +1173,25 @@ void ns_server_init(struct ns_server *s, void *server_data, ns_callback_t cb) {
#ifdef NS_ENABLE_SSL
#ifdef NS_ENABLE_SSL
{
static
int
init_done
;
if
(
!
init_done
)
{
SSL_library_init
();
init_done
++
;
}}
{
static
int
init_done
;
if
(
!
init_done
)
{
SSL_library_init
();
init_done
++
;
}}
s
->
client_ssl_ctx
=
SSL_CTX_new
(
SSLv23_client_method
());
#endif
#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
;
struct
ns_connection
*
conn
,
*
tmp_conn
;
DBG
((
"%p"
,
s
));
DBG
((
"%p"
,
s
));
if
(
s
==
NULL
)
return
;
if
(
s
==
NULL
)
return
;
// Do one last poll, see https://github.com/cesanta/mongoose/issues/286
// 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
[
0
]
!=
INVALID_SOCKET
)
closesocket
(
s
->
ctl
[
0
]);
if
(
s
->
ctl
[
1
]
!=
INVALID_SOCKET
)
closesocket
(
s
->
ctl
[
1
]);
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
)
{
for
(
conn
=
s
->
active_connections
;
conn
!=
NULL
;
conn
=
tmp_conn
)
{
tmp_conn
=
conn
->
next
;
tmp_conn
=
conn
->
next
;
ns_close_conn
(
conn
);
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
// net_skeleton end
#endif // NOEMBED_NET_SKELETON
#endif // NOEMBED_NET_SKELETON
...
@@ -1264,11 +1340,6 @@ enum {
...
@@ -1264,11 +1340,6 @@ enum {
#endif
#endif
#ifndef MONGOOSE_NO_SSI
#ifndef MONGOOSE_NO_SSI
SSI_PATTERN
,
SSI_PATTERN
,
#endif
#ifdef NS_ENABLE_SSL
SSL_CERTIFICATE
,
SSL_CA_CERTIFICATE
,
SSL_MITM_CERTS
,
#endif
#endif
URL_REWRITES
,
URL_REWRITES
,
NUM_OPTIONS
NUM_OPTIONS
...
@@ -1299,7 +1370,7 @@ static const char *static_config_options[] = {
...
@@ -1299,7 +1370,7 @@ static const char *static_config_options[] = {
#ifndef MONGOOSE_NO_FILESYSTEM
#ifndef MONGOOSE_NO_FILESYSTEM
"hide_files_patterns"
,
NULL
,
"hide_files_patterns"
,
NULL
,
"hexdump_file"
,
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
#endif
"listening_port"
,
NULL
,
"listening_port"
,
NULL
,
#ifndef _WIN32
#ifndef _WIN32
...
@@ -1307,18 +1378,13 @@ static const char *static_config_options[] = {
...
@@ -1307,18 +1378,13 @@ static const char *static_config_options[] = {
#endif
#endif
#ifndef MONGOOSE_NO_SSI
#ifndef MONGOOSE_NO_SSI
"ssi_pattern"
,
"**.shtml$|**.shtm$"
,
"ssi_pattern"
,
"**.shtml$|**.shtm$"
,
#endif
#ifdef NS_ENABLE_SSL
"ssl_certificate"
,
NULL
,
"ssl_ca_certificate"
,
NULL
,
"ssl_mitm_certs"
,
NULL
,
#endif
#endif
"url_rewrites"
,
NULL
,
"url_rewrites"
,
NULL
,
NULL
NULL
};
};
struct
mg_server
{
struct
mg_server
{
struct
ns_
server
ns_serve
r
;
struct
ns_
mgr
ns_mg
r
;
union
socket_address
lsa
;
// Listening socket address
union
socket_address
lsa
;
// Listening socket address
mg_handler_t
event_handler
;
mg_handler_t
event_handler
;
char
*
config_options
[
NUM_OPTIONS
];
char
*
config_options
[
NUM_OPTIONS
];
...
@@ -1420,6 +1486,32 @@ void *mg_start_thread(void *(*f)(void *), void *p) {
...
@@ -1420,6 +1486,32 @@ void *mg_start_thread(void *(*f)(void *), void *p) {
}
}
#endif // MONGOOSE_NO_THREADS
#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)
#if defined(_WIN32) && !defined(MONGOOSE_NO_FILESYSTEM)
// Encode 'path' which is assumed UTF-8 string, into UNICODE string.
// Encode 'path' which is assumed UTF-8 string, into UNICODE string.
// wbuf and wbuf_len is a target buffer and its length.
// 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) {
...
@@ -2093,7 +2185,7 @@ static void open_cgi_endpoint(struct connection *conn, const char *prog) {
if
(
start_process
(
conn
->
server
->
config_options
[
CGI_INTERPRETER
],
if
(
start_process
(
conn
->
server
->
config_options
[
CGI_INTERPRETER
],
prog
,
blk
.
buf
,
blk
.
vars
,
dir
,
fds
[
1
])
!=
0
)
{
prog
,
blk
.
buf
,
blk
.
vars
,
dir
,
fds
[
1
])
!=
0
)
{
conn
->
endpoint_type
=
EP_CGI
;
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
;
conn
->
endpoint
.
nc
->
flags
|=
MG_CGI_CONN
;
ns_send
(
conn
->
ns_conn
,
cgi_status
,
sizeof
(
cgi_status
)
-
1
);
ns_send
(
conn
->
ns_conn
,
cgi_status
,
sizeof
(
cgi_status
)
-
1
);
conn
->
mg_conn
.
status_code
=
200
;
conn
->
mg_conn
.
status_code
=
200
;
...
@@ -4160,7 +4252,6 @@ int mg_terminate_ssl(struct mg_connection *c, const char *cert) {
...
@@ -4160,7 +4252,6 @@ int mg_terminate_ssl(struct mg_connection *c, const char *cert) {
SSL_CTX
*
ctx
;
SSL_CTX
*
ctx
;
DBG
((
"%p MITM"
,
conn
));
DBG
((
"%p MITM"
,
conn
));
SSL_library_init
();
if
((
ctx
=
SSL_CTX_new
(
SSLv23_server_method
()))
==
NULL
)
return
0
;
if
((
ctx
=
SSL_CTX_new
(
SSLv23_server_method
()))
==
NULL
)
return
0
;
SSL_CTX_use_certificate_file
(
ctx
,
cert
,
1
);
SSL_CTX_use_certificate_file
(
ctx
,
cert
,
1
);
...
@@ -4170,7 +4261,7 @@ int mg_terminate_ssl(struct mg_connection *c, const char *cert) {
...
@@ -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.
// When clear-text reply is pushed to client, switch to SSL mode.
// TODO(lsm): check for send() failure
// TODO(lsm): check for send() failure
send
(
conn
->
ns_conn
->
sock
,
ok
,
sizeof
(
ok
)
-
1
,
0
);
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
->
ns_conn
->
send_iobuf
.
len
=
0
;
conn
->
endpoint_type
=
EP_USER
;
// To keep-alive in close_local_endpoint()
conn
->
endpoint_type
=
EP_USER
;
// To keep-alive in close_local_endpoint()
close_local_endpoint
(
conn
);
// Clean up current CONNECT request
close_local_endpoint
(
conn
);
// Clean up current CONNECT request
...
@@ -4182,12 +4273,12 @@ int mg_terminate_ssl(struct mg_connection *c, const char *cert) {
...
@@ -4182,12 +4273,12 @@ int mg_terminate_ssl(struct mg_connection *c, const char *cert) {
}
}
#endif
#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
connection
*
conn
=
MG_CONN_2_CONN
(
c
);
struct
ns_server
*
server
=
&
conn
->
server
->
ns_server
;
struct
ns_connection
*
pc
;
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
;
conn
->
ns_conn
->
flags
|=
NSF_CLOSE_IMMEDIATELY
;
return
0
;
return
0
;
}
}
...
@@ -4196,12 +4287,12 @@ int mg_forward(struct mg_connection *c, const char *host, int port, int ssl) {
...
@@ -4196,12 +4287,12 @@ int mg_forward(struct mg_connection *c, const char *host, int port, int ssl) {
pc
->
flags
|=
MG_PROXY_CONN
;
pc
->
flags
|=
MG_PROXY_CONN
;
conn
->
endpoint_type
=
EP_PROXY
;
conn
->
endpoint_type
=
EP_PROXY
;
conn
->
endpoint
.
nc
=
pc
;
conn
->
endpoint
.
nc
=
pc
;
DBG
((
"%p [%s] [%s:%d] -> %p %p"
,
DBG
((
"%p [%s] [%s] -> %p %p"
,
conn
,
c
->
uri
,
addr
,
pc
,
conn
->
ns_conn
->
ssl
));
conn
,
c
->
uri
,
host
,
port
,
pc
,
conn
->
ns_conn
->
ssl
));
if
(
strcmp
(
c
->
request_method
,
"CONNECT"
)
==
0
)
{
if
(
strcmp
(
c
->
request_method
,
"CONNECT"
)
==
0
)
{
// For CONNECT request, reply with 200 OK. Tunnel is established.
// 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
{
}
else
{
// Strip "http://host:port" part from the URI
// Strip "http://host:port" part from the URI
if
(
memcmp
(
c
->
uri
,
"http://"
,
7
)
==
0
)
c
->
uri
+=
7
;
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) {
...
@@ -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
)
{
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
;
unsigned
short
port
=
80
;
struct
mg_connection
*
c
=
&
conn
->
mg_conn
;
struct
mg_connection
*
c
=
&
conn
->
mg_conn
;
int
n
=
0
;
int
n
=
0
;
...
@@ -4225,25 +4316,9 @@ static void proxify_connection(struct connection *conn) {
...
@@ -4225,25 +4316,9 @@ static void proxify_connection(struct connection *conn) {
n
=
0
;
n
=
0
;
}
}
#ifdef NS_ENABLE_SSL
snprintf
(
addr
,
sizeof
(
addr
),
"%s://%s:%hu"
,
// Find out whether we should be in the MITM mode
conn
->
ns_conn
->
ssl
!=
NULL
?
"ssl"
:
"tcp"
,
host
,
port
);
{
if
(
n
<=
0
||
!
mg_forward
(
c
,
addr
))
{
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
{
conn
->
ns_conn
->
flags
|=
NSF_CLOSE_IMMEDIATELY
;
conn
->
ns_conn
->
flags
|=
NSF_CLOSE_IMMEDIATELY
;
}
}
}
}
...
@@ -4535,12 +4610,11 @@ static void process_response(struct connection *conn) {
...
@@ -4535,12 +4610,11 @@ static void process_response(struct connection *conn) {
}
}
}
}
struct
mg_connection
*
mg_connect
(
struct
mg_server
*
server
,
const
char
*
host
,
struct
mg_connection
*
mg_connect
(
struct
mg_server
*
server
,
const
char
*
addr
)
{
int
port
,
int
use_ssl
)
{
struct
ns_connection
*
nsconn
;
struct
ns_connection
*
nsconn
;
struct
connection
*
conn
;
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
(
nsconn
==
NULL
)
return
0
;
if
((
conn
=
(
struct
connection
*
)
calloc
(
1
,
sizeof
(
*
conn
)))
==
NULL
)
{
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,
...
@@ -4555,7 +4629,7 @@ struct mg_connection *mg_connect(struct mg_server *server, const char *host,
conn
->
server
=
server
;
conn
->
server
=
server
;
conn
->
endpoint_type
=
EP_CLIENT
;
conn
->
endpoint_type
=
EP_CLIENT
;
//conn->handler = handler;
//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
;
conn
->
ns_conn
->
flags
=
NSF_CONNECTING
;
return
&
conn
->
mg_conn
;
return
&
conn
->
mg_conn
;
...
@@ -4684,7 +4758,7 @@ static void transfer_file_data(struct connection *conn) {
...
@@ -4684,7 +4758,7 @@ static void transfer_file_data(struct connection *conn) {
}
}
int
mg_poll_server
(
struct
mg_server
*
server
,
int
milliseconds
)
{
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
)
{
void
mg_destroy_server
(
struct
mg_server
**
server
)
{
...
@@ -4692,7 +4766,7 @@ 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
;
struct
mg_server
*
s
=
*
server
;
int
i
;
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
++
)
{
for
(
i
=
0
;
i
<
(
int
)
ARRAY_SIZE
(
s
->
config_options
);
i
++
)
{
free
(
s
->
config_options
[
i
]);
// It is OK to free(NULL)
free
(
s
->
config_options
[
i
]);
// It is OK to free(NULL)
}
}
...
@@ -4701,34 +4775,15 @@ void mg_destroy_server(struct mg_server **server) {
...
@@ -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
mg_connection
*
mg_next
(
struct
mg_server
*
s
,
struct
mg_connection
*
c
)
{
struct
connection
*
conn
=
MG_CONN_2_CONN
(
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
);
c
==
NULL
?
NULL
:
conn
->
ns_conn
);
if
(
nc
!=
NULL
&&
nc
->
connection_data
!=
NULL
)
{
return
nc
==
NULL
?
NULL
:
return
&
((
struct
connection
*
)
nc
->
connection_data
)
->
mg_conn
;
&
((
struct
connection
*
)
nc
->
connection_data
)
->
mg_conn
;
}
else
{
}
return
NULL
;
}
// 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
);
}
}
static
int
get_var
(
const
char
*
data
,
size_t
data_len
,
const
char
*
name
,
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,
...
@@ -4886,18 +4941,18 @@ const char *mg_set_option(struct mg_server *server, const char *name,
DBG
((
"%s [%s]"
,
name
,
*
v
));
DBG
((
"%s [%s]"
,
name
,
*
v
));
if
(
ind
==
LISTENING_PORT
)
{
if
(
ind
==
LISTENING_PORT
)
{
int
port
=
ns_bind
(
&
server
->
ns_server
,
value
);
struct
ns_connection
*
c
=
ns_bind
(
&
server
->
ns_mgr
,
value
,
NULL
);
if
(
port
<
0
)
{
if
(
c
==
NULL
)
{
error_msg
=
"Cannot bind to port"
;
error_msg
=
"Cannot bind to port"
;
}
else
{
}
else
{
char
buf
[
100
];
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
);
free
(
*
v
);
*
v
=
mg_strdup
(
buf
);
*
v
=
mg_strdup
(
buf
);
}
}
#ifndef MONGOOSE_NO_FILESYSTEM
#ifndef MONGOOSE_NO_FILESYSTEM
}
else
if
(
ind
==
HEXDUMP_FILE
)
{
}
else
if
(
ind
==
HEXDUMP_FILE
)
{
server
->
ns_
serve
r
.
hexdump_file
=
*
v
;
server
->
ns_
mg
r
.
hexdump_file
=
*
v
;
#endif
#endif
#ifndef _WIN32
#ifndef _WIN32
}
else
if
(
ind
==
RUN_AS_USER
)
{
}
else
if
(
ind
==
RUN_AS_USER
)
{
...
@@ -4909,21 +4964,6 @@ const char *mg_set_option(struct mg_server *server, const char *name,
...
@@ -4909,21 +4964,6 @@ const char *mg_set_option(struct mg_server *server, const char *name,
}
else
if
(
setuid
(
pw
->
pw_uid
)
!=
0
)
{
}
else
if
(
setuid
(
pw
->
pw_uid
)
!=
0
)
{
error_msg
=
"setuid() failed"
;
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
#endif
}
}
...
@@ -4943,7 +4983,7 @@ static void set_ips(struct ns_connection *nc, int is_rem) {
...
@@ -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
)
{
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
;
struct
connection
*
conn
;
if
(
!
check_acl
(
server
->
config_options
[
ACCESS_CONTROL_LIST
],
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) {
...
@@ -4957,7 +4997,7 @@ static void on_accept(struct ns_connection *nc, union socket_address *sa) {
// Initialize the rest of connection attributes
// Initialize the rest of connection attributes
conn
->
server
=
server
;
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
,
1
);
set_ips
(
nc
,
0
);
set_ips
(
nc
,
0
);
}
}
...
@@ -5007,7 +5047,7 @@ static void mg_ev_handler(struct ns_connection *nc, enum ns_event ev, void *p) {
...
@@ -5007,7 +5047,7 @@ static void mg_ev_handler(struct ns_connection *nc, enum ns_event ev, void *p) {
if
(
conn
!=
NULL
)
{
if
(
conn
!=
NULL
)
{
conn
->
num_bytes_recv
+=
*
(
int
*
)
p
;
conn
->
num_bytes_recv
+=
*
(
int
*
)
p
;
}
}
if
(
nc
->
flags
&
NSF_ACCEPTED
)
{
if
(
nc
->
listener
!=
NULL
)
{
on_recv_data
(
conn
);
on_recv_data
(
conn
);
#ifndef MONGOOSE_NO_CGI
#ifndef MONGOOSE_NO_CGI
}
else
if
(
nc
->
flags
&
MG_CGI_CONN
)
{
}
else
if
(
nc
->
flags
&
MG_CGI_CONN
)
{
...
@@ -5110,23 +5150,25 @@ void mg_wakeup_server_ex(struct mg_server *server, mg_handler_t cb,
...
@@ -5110,23 +5150,25 @@ void mg_wakeup_server_ex(struct mg_server *server, mg_handler_t cb,
va_end
(
ap
);
va_end
(
ap
);
// "len + 1" is to include terminating \0 in the message
// "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
)
{
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) {
void mg_set_listening_socket(struct mg_server *server, int sock) {
if
(
server
->
ns_
serve
r
.
listening_sock
!=
INVALID_SOCKET
)
{
if (server->ns_
mg
r.listening_sock != INVALID_SOCKET) {
closesocket
(
server
->
ns_
serve
r
.
listening_sock
);
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) {
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
*
mg_get_option
(
const
struct
mg_server
*
server
,
const
char
*
name
)
{
const
char
**
opts
=
(
const
char
**
)
server
->
config_options
;
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) {
...
@@ -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
*
mg_create_server
(
void
*
server_data
,
mg_handler_t
handler
)
{
struct
mg_server
*
server
=
(
struct
mg_server
*
)
calloc
(
1
,
sizeof
(
*
server
));
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
);
set_default_option_values
(
server
->
config_options
);
server
->
event_handler
=
handler
;
server
->
event_handler
=
handler
;
return
server
;
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 @@
...
@@ -15,7 +15,7 @@
// Alternatively, you can license this library under a commercial
// Alternatively, you can license this library under a commercial
// license, as set out in <http://cesanta.com/>.
// 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
#ifndef MONGOOSE_HEADER_INCLUDED
#define MONGOOSE_HEADER_INCLUDED
#define MONGOOSE_HEADER_INCLUDED
...
@@ -55,7 +55,7 @@ struct mg_connection {
...
@@ -55,7 +55,7 @@ struct mg_connection {
int
wsbits
;
// First byte of the websocket frame
int
wsbits
;
// First byte of the websocket frame
void
*
server_param
;
// Parameter passed to mg_add_uri_handler()
void
*
server_param
;
// Parameter passed to mg_add_uri_handler()
void
*
connection_param
;
// Placeholder for connection-specific data
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
struct
mg_server
;
// Opaque structure describing server instance
...
@@ -95,11 +95,10 @@ const char **mg_get_valid_option_names(void);
...
@@ -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
);
const
char
*
mg_get_option
(
const
struct
mg_server
*
server
,
const
char
*
name
);
void
mg_set_listening_socket
(
struct
mg_server
*
,
int
sock
);
void
mg_set_listening_socket
(
struct
mg_server
*
,
int
sock
);
int
mg_get_listening_socket
(
struct
mg_server
*
);
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
*
);
struct
mg_connection
*
mg_next
(
struct
mg_server
*
,
struct
mg_connection
*
);
void
mg_wakeup_server
(
struct
mg_server
*
);
void
mg_wakeup_server
(
struct
mg_server
*
);
void
mg_wakeup_server_ex
(
struct
mg_server
*
,
mg_handler_t
,
const
char
*
,
...);
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
// Connection management functions
void
mg_send_status
(
struct
mg_connection
*
,
int
status_code
);
void
mg_send_status
(
struct
mg_connection
*
,
int
status_code
);
...
@@ -127,6 +126,7 @@ int mg_parse_multipart(const char *buf, int buf_len,
...
@@ -127,6 +126,7 @@ int mg_parse_multipart(const char *buf, int buf_len,
char
*
file_name
,
int
file_name_len
,
char
*
file_name
,
int
file_name_len
,
const
char
**
data
,
int
*
data_len
);
const
char
**
data
,
int
*
data_len
);
// Utility functions
// Utility functions
void
*
mg_start_thread
(
void
*
(
*
func
)(
void
*
),
void
*
param
);
void
*
mg_start_thread
(
void
*
(
*
func
)(
void
*
),
void
*
param
);
char
*
mg_md5
(
char
buf
[
33
],
...);
char
*
mg_md5
(
char
buf
[
33
],
...);
...
@@ -134,7 +134,7 @@ int mg_authorize_digest(struct mg_connection *c, FILE *fp);
...
@@ -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_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_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_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_mmap
(
FILE
*
fp
,
size_t
size
);
void
mg_munmap
(
void
*
p
,
size_t
size
);
void
mg_munmap
(
void
*
p
,
size_t
size
);
...
@@ -147,7 +147,6 @@ struct mg_expansion {
...
@@ -147,7 +147,6 @@ struct mg_expansion {
void
mg_template
(
struct
mg_connection
*
,
const
char
*
text
,
void
mg_template
(
struct
mg_connection
*
,
const
char
*
text
,
struct
mg_expansion
*
expansions
);
struct
mg_expansion
*
expansions
);
#ifdef __cplusplus
#ifdef __cplusplus
}
}
#endif // __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