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
ee55d38b
Commit
ee55d38b
authored
Feb 01, 2013
by
Sergey Lyubka
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
API CHANGE: using struct mg_callbacks
parent
62162ff3
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
284 additions
and
386 deletions
+284
-386
chat.c
examples/chat.c
+20
-26
hello.c
examples/hello.c
+35
-21
post.c
examples/post.c
+30
-35
upload.c
examples/upload.c
+29
-27
websocket.c
examples/websocket.c
+46
-45
main.c
main.c
+8
-9
mongoose.c
mongoose.c
+54
-59
mongoose.h
mongoose.h
+13
-115
test.pl
test/test.pl
+1
-1
unit_test.c
test/unit_test.c
+48
-48
No files found.
examples/chat.c
View file @
ee55d38b
...
@@ -325,34 +325,25 @@ static void redirect_to_ssl(struct mg_connection *conn,
...
@@ -325,34 +325,25 @@ static void redirect_to_ssl(struct mg_connection *conn,
}
}
}
}
static
void
*
event_handler
(
enum
mg_event
event
,
static
int
begin_request_handler
(
struct
mg_connection
*
conn
)
{
struct
mg_connection
*
conn
)
{
const
struct
mg_request_info
*
request_info
=
mg_get_request_info
(
conn
);
const
struct
mg_request_info
*
request_info
=
mg_get_request_info
(
conn
);
void
*
processed
=
"yes"
;
int
processed
=
1
;
if
(
event
==
MG_NEW_REQUEST
)
{
if
(
!
request_info
->
is_ssl
)
{
if
(
!
request_info
->
is_ssl
)
{
redirect_to_ssl
(
conn
,
request_info
);
redirect_to_ssl
(
conn
,
request_info
);
}
else
if
(
!
is_authorized
(
conn
,
request_info
))
{
}
else
if
(
!
is_authorized
(
conn
,
request_info
))
{
redirect_to_login
(
conn
,
request_info
);
redirect_to_login
(
conn
,
request_info
);
}
else
if
(
strcmp
(
request_info
->
uri
,
authorize_url
)
==
0
)
{
}
else
if
(
strcmp
(
request_info
->
uri
,
authorize_url
)
==
0
)
{
authorize
(
conn
,
request_info
);
authorize
(
conn
,
request_info
);
}
else
if
(
strcmp
(
request_info
->
uri
,
"/ajax/get_messages"
)
==
0
)
{
}
else
if
(
strcmp
(
request_info
->
uri
,
"/ajax/get_messages"
)
==
0
)
{
ajax_get_messages
(
conn
,
request_info
);
ajax_get_messages
(
conn
,
request_info
);
}
else
if
(
strcmp
(
request_info
->
uri
,
"/ajax/send_message"
)
==
0
)
{
}
else
if
(
strcmp
(
request_info
->
uri
,
"/ajax/send_message"
)
==
0
)
{
ajax_send_message
(
conn
,
request_info
);
ajax_send_message
(
conn
,
request_info
);
}
else
{
// No suitable handler found, mark as not processed. Mongoose will
// try to serve the request.
processed
=
NULL
;
}
}
else
if
(
event
==
MG_EVENT_LOG
)
{
printf
(
"%s
\n
"
,
(
const
char
*
)
mg_get_request_info
(
conn
)
->
ev_data
);
processed
=
NULL
;
}
else
{
}
else
{
processed
=
NULL
;
// No suitable handler found, mark as not processed. Mongoose will
// try to serve the request.
processed
=
0
;
}
}
return
processed
;
return
processed
;
}
}
...
@@ -365,6 +356,7 @@ static const char *options[] = {
...
@@ -365,6 +356,7 @@ static const char *options[] = {
};
};
int
main
(
void
)
{
int
main
(
void
)
{
struct
mg_callbacks
callbacks
;
struct
mg_context
*
ctx
;
struct
mg_context
*
ctx
;
// Initialize random number generator. It will be used later on for
// Initialize random number generator. It will be used later on for
...
@@ -372,7 +364,9 @@ int main(void) {
...
@@ -372,7 +364,9 @@ int main(void) {
srand
((
unsigned
)
time
(
0
));
srand
((
unsigned
)
time
(
0
));
// Setup and start Mongoose
// Setup and start Mongoose
if
((
ctx
=
mg_start
(
&
event_handler
,
NULL
,
options
))
==
NULL
)
{
memset
(
&
callbacks
,
0
,
sizeof
(
callbacks
));
callbacks
.
begin_request
=
begin_request_handler
;
if
((
ctx
=
mg_start
(
&
callbacks
,
NULL
,
options
))
==
NULL
)
{
printf
(
"%s
\n
"
,
"Cannot start chat server, fatal exit"
);
printf
(
"%s
\n
"
,
"Cannot start chat server, fatal exit"
);
exit
(
EXIT_FAILURE
);
exit
(
EXIT_FAILURE
);
}
}
...
...
examples/hello.c
View file @
ee55d38b
...
@@ -2,35 +2,49 @@
...
@@ -2,35 +2,49 @@
#include <string.h>
#include <string.h>
#include "mongoose.h"
#include "mongoose.h"
static
void
*
callback
(
enum
mg_event
event
,
// This function will be called by mongoose on every new request.
struct
mg_connection
*
conn
)
{
static
int
begin_request_handler
(
struct
mg_connection
*
conn
)
{
const
struct
mg_request_info
*
request_info
=
mg_get_request_info
(
conn
);
const
struct
mg_request_info
*
request_info
=
mg_get_request_info
(
conn
);
char
content
[
100
];
if
(
event
==
MG_NEW_REQUEST
)
{
// Prepare the message we're going to send
char
content
[
1024
];
int
content_length
=
snprintf
(
content
,
sizeof
(
content
),
int
content_length
=
snprintf
(
content
,
sizeof
(
content
)
,
"Hello from mongoose! Remote port: %d"
,
"Hello from mongoose! Remote port: %d"
,
request_info
->
remote_port
);
request_info
->
remote_port
);
mg_printf
(
conn
,
// Send HTTP reply to the client
"HTTP/1.1 200 OK
\r\n
"
mg_printf
(
conn
,
"Content-Type: text/plain
\r\n
"
"HTTP/1.1 200 OK
\r\n
"
"Content-Length: %d
\r\n
"
// Always set Content-Length
"Content-Type: text/plain
\r\n
"
"
\r\n
"
"Content-Length: %d
\r\n
"
// Always set Content-Length
"%s"
,
"
\r\n
"
content_length
,
content
);
"%s"
,
// Mark as processed
content_length
,
content
);
return
""
;
}
else
{
// Returning non-zero tells mongoose that our function has replied to
return
NULL
;
// the client, and mongoose should not send client any more data.
}
return
1
;
}
}
int
main
(
void
)
{
int
main
(
void
)
{
struct
mg_context
*
ctx
;
struct
mg_context
*
ctx
;
struct
mg_callbacks
callbacks
;
// List of options. Last element must be NULL.
const
char
*
options
[]
=
{
"listening_ports"
,
"8080"
,
NULL
};
const
char
*
options
[]
=
{
"listening_ports"
,
"8080"
,
NULL
};
ctx
=
mg_start
(
&
callback
,
NULL
,
options
);
// Prepare callbacks structure. We have only one callback, the rest are NULL.
getchar
();
// Wait until user hits "enter"
memset
(
&
callbacks
,
0
,
sizeof
(
callbacks
));
callbacks
.
begin_request
=
begin_request_handler
;
// Start the web server.
ctx
=
mg_start
(
&
callbacks
,
NULL
,
options
);
// Wait until user hits "enter". Server is running in separate thread.
// Navigating to http://localhost:8080 will invoke begin_request_handler().
getchar
();
// Stop the server.
mg_stop
(
ctx
);
mg_stop
(
ctx
);
return
0
;
return
0
;
...
...
examples/post.c
View file @
ee55d38b
...
@@ -10,50 +10,45 @@ static const char *html_form =
...
@@ -10,50 +10,45 @@ static const char *html_form =
"<input type=
\"
submit
\"
/>"
"<input type=
\"
submit
\"
/>"
"</form></body></html>"
;
"</form></body></html>"
;
static
void
*
callback
(
enum
mg_event
event
,
static
int
begin_request_handler
(
struct
mg_connection
*
conn
)
{
struct
mg_connection
*
conn
)
{
const
struct
mg_request_info
*
ri
=
mg_get_request_info
(
conn
);
const
struct
mg_request_info
*
ri
=
mg_get_request_info
(
conn
);
char
post_data
[
1024
],
input1
[
sizeof
(
post_data
)],
input2
[
sizeof
(
post_data
)];
if
(
event
==
MG_NEW_REQUEST
)
{
int
post_data_len
;
if
(
!
strcmp
(
ri
->
uri
,
"/handle_post_request"
))
{
// User has submitted a form, show submitted data and a variable value
if
(
!
strcmp
(
ri
->
uri
,
"/handle_post_request"
))
{
char
post_data
[
1024
],
// User has submitted a form, show submitted data and a variable value
input1
[
sizeof
(
post_data
)],
input2
[
sizeof
(
post_data
)];
post_data_len
=
mg_read
(
conn
,
post_data
,
sizeof
(
post_data
));
int
post_data_len
;
// Parse form data. input1 and input2 are guaranteed to be NUL-terminated
// Read POST data
mg_get_var
(
post_data
,
post_data_len
,
"input_1"
,
input1
,
sizeof
(
input1
));
post_data_len
=
mg_read
(
conn
,
post_data
,
sizeof
(
post_data
));
mg_get_var
(
post_data
,
post_data_len
,
"input_2"
,
input2
,
sizeof
(
input2
));
// Parse form data. input1 and input2 are guaranteed to be NUL-terminated
// Send reply to the client, showing submitted form values.
mg_get_var
(
post_data
,
post_data_len
,
"input_1"
,
input1
,
sizeof
(
input1
));
mg_printf
(
conn
,
"HTTP/1.0 200 OK
\r\n
"
mg_get_var
(
post_data
,
post_data_len
,
"input_2"
,
input2
,
sizeof
(
input2
));
"Content-Type: text/plain
\r\n\r\n
"
"Submitted data: [%.*s]
\n
"
mg_printf
(
conn
,
"HTTP/1.0 200 OK
\r\n
"
"Submitted data length: %d bytes
\n
"
"Content-Type: text/plain
\r\n\r\n
"
"input_1: [%s]
\n
"
"Submitted data: [%.*s]
\n
"
"input_2: [%s]
\n
"
,
"Submitted data length: %d bytes
\n
"
post_data_len
,
post_data
,
post_data_len
,
input1
,
input2
);
"input_1: [%s]
\n
"
"input_2: [%s]
\n
"
,
post_data_len
,
post_data
,
post_data_len
,
input1
,
input2
);
}
else
{
// Show HTML form.
mg_printf
(
conn
,
"HTTP/1.0 200 OK
\r\n
"
"Content-Length: %d
\r\n
"
"Content-Type: text/html
\r\n\r\n
%s"
,
(
int
)
strlen
(
html_form
),
html_form
);
}
// Mark as processed
return
""
;
}
else
{
}
else
{
return
NULL
;
// Show HTML form.
mg_printf
(
conn
,
"HTTP/1.0 200 OK
\r\n
"
"Content-Length: %d
\r\n
"
"Content-Type: text/html
\r\n\r\n
%s"
,
(
int
)
strlen
(
html_form
),
html_form
);
}
}
return
1
;
// Mark request as processed
}
}
int
main
(
void
)
{
int
main
(
void
)
{
struct
mg_context
*
ctx
;
struct
mg_context
*
ctx
;
const
char
*
options
[]
=
{
"listening_ports"
,
"8080"
,
NULL
};
const
char
*
options
[]
=
{
"listening_ports"
,
"8080"
,
NULL
};
struct
mg_callbacks
callbacks
;
ctx
=
mg_start
(
&
callback
,
NULL
,
options
);
memset
(
&
callbacks
,
0
,
sizeof
(
callbacks
));
callbacks
.
begin_request
=
begin_request_handler
;
ctx
=
mg_start
(
&
callbacks
,
NULL
,
options
);
getchar
();
// Wait until user hits "enter"
getchar
();
// Wait until user hits "enter"
mg_stop
(
ctx
);
mg_stop
(
ctx
);
...
...
examples/upload.c
View file @
ee55d38b
...
@@ -17,42 +17,44 @@ typedef __int64 int64_t;
...
@@ -17,42 +17,44 @@ typedef __int64 int64_t;
#include "mongoose.h"
#include "mongoose.h"
static
void
*
callback
(
enum
mg_event
event
,
struct
mg_connection
*
conn
)
{
static
int
begin_request_handler
(
struct
mg_connection
*
conn
)
{
if
(
event
==
MG_NEW_REQUEST
)
{
if
(
!
strcmp
(
mg_get_request_info
(
conn
)
->
uri
,
"/handle_post_request"
))
{
if
(
!
strcmp
(
mg_get_request_info
(
conn
)
->
uri
,
"/handle_post_request"
))
{
mg_printf
(
conn
,
"%s"
,
"HTTP/1.0 200 OK
\r\n\r\n
"
);
mg_printf
(
conn
,
"%s"
,
"HTTP/1.0 200 OK
\r\n\r\n
"
);
mg_upload
(
conn
,
"/tmp"
);
mg_upload
(
conn
,
"/tmp"
);
}
else
{
}
else
{
// Show HTML form. Make sure it has enctype="multipart/form-data" attr.
// Show HTML form. Make sure it has enctype="multipart/form-data" attr.
static
const
char
*
html_form
=
static
const
char
*
html_form
=
"<html><body>Upload example."
"<html><body>Upload example."
"<form method=
\"
POST
\"
action=
\"
/handle_post_request
\"
"
"<form method=
\"
POST
\"
action=
\"
/handle_post_request
\"
"
" enctype=
\"
multipart/form-data
\"
>"
" enctype=
\"
multipart/form-data
\"
>"
"<input type=
\"
file
\"
name=
\"
file
\"
/> <br/>"
"<input type=
\"
file
\"
name=
\"
file
\"
/> <br/>"
"<input type=
\"
submit
\"
value=
\"
Upload
\"
/>"
"<input type=
\"
submit
\"
value=
\"
Upload
\"
/>"
"</form></body></html>"
;
"</form></body></html>"
;
mg_printf
(
conn
,
"HTTP/1.0 200 OK
\r\n
"
mg_printf
(
conn
,
"HTTP/1.0 200 OK
\r\n
"
"Content-Length: %d
\r\n
"
"Content-Length: %d
\r\n
"
"Content-Type: text/html
\r\n\r\n
%s"
,
"Content-Type: text/html
\r\n\r\n
%s"
,
(
int
)
strlen
(
html_form
),
html_form
);
(
int
)
strlen
(
html_form
),
html_form
);
}
// Mark as processed
return
""
;
}
else
if
(
event
==
MG_UPLOAD
)
{
mg_printf
(
conn
,
"Saved [%s]"
,
mg_get_request_info
(
conn
)
->
ev_data
);
}
}
return
NULL
;
// Mark request as processed
return
1
;
}
static
void
upload_handler
(
struct
mg_connection
*
conn
,
const
char
*
path
)
{
mg_printf
(
conn
,
"Saved [%s]"
,
path
);
}
}
int
main
(
void
)
{
int
main
(
void
)
{
struct
mg_context
*
ctx
;
struct
mg_context
*
ctx
;
const
char
*
options
[]
=
{
"listening_ports"
,
"8080"
,
NULL
};
const
char
*
options
[]
=
{
"listening_ports"
,
"8080"
,
NULL
};
struct
mg_callbacks
callbacks
;
ctx
=
mg_start
(
&
callback
,
NULL
,
options
);
memset
(
&
callbacks
,
0
,
sizeof
(
callbacks
));
callbacks
.
begin_request
=
begin_request_handler
;
callbacks
.
upload
=
upload_handler
;
ctx
=
mg_start
(
&
callbacks
,
NULL
,
options
);
getchar
();
// Wait until user hits "enter"
getchar
();
// Wait until user hits "enter"
pause
();
mg_stop
(
ctx
);
mg_stop
(
ctx
);
return
0
;
return
0
;
...
...
examples/websocket.c
View file @
ee55d38b
...
@@ -5,69 +5,70 @@
...
@@ -5,69 +5,70 @@
#include <string.h>
#include <string.h>
#include "mongoose.h"
#include "mongoose.h"
static
void
*
callback
(
enum
mg_event
event
,
struct
mg_connection
*
conn
)
{
static
void
websocket_ready_handler
(
struct
mg_connection
*
conn
)
{
if
(
event
==
MG_WEBSOCKET_READY
)
{
unsigned
char
buf
[
40
];
unsigned
char
buf
[
40
]
;
buf
[
0
]
=
0x81
;
buf
[
0
]
=
0x81
;
buf
[
1
]
=
snprintf
((
char
*
)
buf
+
2
,
sizeof
(
buf
)
-
2
,
"%s"
,
"server ready"
)
;
buf
[
1
]
=
snprintf
((
char
*
)
buf
+
2
,
sizeof
(
buf
)
-
2
,
"%s"
,
"server ready"
);
mg_write
(
conn
,
buf
,
2
+
buf
[
1
]
);
mg_write
(
conn
,
buf
,
2
+
buf
[
1
]);
}
return
""
;
// MG_WEBSOCKET_READY return value is ignored
}
else
if
(
event
==
MG_WEBSOCKET_MESSAGE
)
{
static
int
websocket_data_handler
(
struct
mg_connection
*
conn
)
{
unsigned
char
buf
[
200
],
reply
[
200
];
unsigned
char
buf
[
200
],
reply
[
200
];
int
n
,
i
,
mask_len
,
xor
,
msg_len
,
len
;
int
n
,
i
,
mask_len
,
xor
,
msg_len
,
len
;
// Read message from the client.
// Read message from the client.
// Accept only small (<126 bytes) messages.
// Accept only small (<126 bytes) messages.
len
=
0
;
len
=
0
;
msg_len
=
mask_len
=
0
;
msg_len
=
mask_len
=
0
;
for
(;;)
{
for
(;;)
{
if
((
n
=
mg_read
(
conn
,
buf
+
len
,
sizeof
(
buf
)
-
len
))
<=
0
)
{
if
((
n
=
mg_read
(
conn
,
buf
+
len
,
sizeof
(
buf
)
-
len
))
<=
0
)
{
return
""
;
// Read error, close websocket
return
0
;
// Read error, close websocket
}
len
+=
n
;
if
(
len
>=
2
)
{
msg_len
=
buf
[
1
]
&
127
;
mask_len
=
(
buf
[
1
]
&
128
)
?
4
:
0
;
if
(
msg_len
>
125
)
{
return
0
;
// Message is too long, close websocket
}
}
len
+=
n
;
// If we've buffered the whole message, exit the loop
if
(
len
>=
2
)
{
if
(
len
>=
2
+
mask_len
+
msg_len
)
{
msg_len
=
buf
[
1
]
&
127
;
break
;
mask_len
=
(
buf
[
1
]
&
128
)
?
4
:
0
;
if
(
msg_len
>
125
)
{
return
""
;
// Message is too long, close websocket
}
// If we've buffered the whole message, exit the loop
if
(
len
>=
2
+
mask_len
+
msg_len
)
{
break
;
}
}
}
}
}
}
// Prepare frame
// Prepare frame
reply
[
0
]
=
0x81
;
// text, FIN set
reply
[
0
]
=
0x81
;
// text, FIN set
reply
[
1
]
=
msg_len
;
reply
[
1
]
=
msg_len
;
// Copy message from request to reply, applying the mask if required.
// Copy message from request to reply, applying the mask if required.
for
(
i
=
0
;
i
<
msg_len
;
i
++
)
{
for
(
i
=
0
;
i
<
msg_len
;
i
++
)
{
xor
=
mask_len
==
0
?
0
:
buf
[
2
+
(
i
%
4
)];
xor
=
mask_len
==
0
?
0
:
buf
[
2
+
(
i
%
4
)];
reply
[
i
+
2
]
=
buf
[
i
+
2
+
mask_len
]
^
xor
;
reply
[
i
+
2
]
=
buf
[
i
+
2
+
mask_len
]
^
xor
;
}
}
// Echo the message back to the client
// Echo the message back to the client
mg_write
(
conn
,
reply
,
2
+
msg_len
);
mg_write
(
conn
,
reply
,
2
+
msg_len
);
// Return non-NULL means stoping websocket conversation.
// Returnint zero means stoping websocket conversation.
// Close the conversation if client has sent us "exit" string.
// Close the conversation if client has sent us "exit" string.
return
memcmp
(
reply
+
2
,
"exit"
,
4
)
==
0
?
""
:
NULL
;
return
memcmp
(
reply
+
2
,
"exit"
,
4
);
}
else
{
return
NULL
;
}
}
}
int
main
(
void
)
{
int
main
(
void
)
{
struct
mg_context
*
ctx
;
struct
mg_context
*
ctx
;
struct
mg_callbacks
callbacks
;
const
char
*
options
[]
=
{
const
char
*
options
[]
=
{
"listening_ports"
,
"8080"
,
"listening_ports"
,
"8080"
,
"document_root"
,
"websocket_html_root"
,
"document_root"
,
"websocket_html_root"
,
NULL
NULL
};
};
ctx
=
mg_start
(
&
callback
,
NULL
,
options
);
memset
(
&
callbacks
,
0
,
sizeof
(
callbacks
));
callbacks
.
websocket_ready
=
websocket_ready_handler
;
callbacks
.
websocket_data
=
websocket_data_handler
;
ctx
=
mg_start
(
&
callbacks
,
NULL
,
options
);
getchar
();
// Wait until user hits "enter"
getchar
();
// Wait until user hits "enter"
mg_stop
(
ctx
);
mg_stop
(
ctx
);
...
...
main.c
View file @
ee55d38b
...
@@ -266,17 +266,14 @@ static void init_server_name(void) {
...
@@ -266,17 +266,14 @@ static void init_server_name(void) {
mg_version
());
mg_version
());
}
}
static
void
*
mongoose_callback
(
enum
mg_event
ev
,
struct
mg_connection
*
conn
)
{
static
int
log_message
(
const
struct
mg_connection
*
conn
,
const
char
*
message
)
{
if
(
ev
==
MG_EVENT_LOG
)
{
(
void
)
conn
;
printf
(
"%s
\n
"
,
(
const
char
*
)
mg_get_request_info
(
conn
)
->
ev_data
);
printf
(
"%s
\n
"
,
message
);
}
return
0
;
// Returning NULL marks request as not handled, signalling mongoose to
// proceed with handling it.
return
NULL
;
}
}
static
void
start_mongoose
(
int
argc
,
char
*
argv
[])
{
static
void
start_mongoose
(
int
argc
,
char
*
argv
[])
{
struct
mg_callbacks
callbacks
;
char
*
options
[
MAX_OPTIONS
];
char
*
options
[
MAX_OPTIONS
];
int
i
;
int
i
;
...
@@ -302,7 +299,9 @@ static void start_mongoose(int argc, char *argv[]) {
...
@@ -302,7 +299,9 @@ static void start_mongoose(int argc, char *argv[]) {
signal
(
SIGINT
,
signal_handler
);
signal
(
SIGINT
,
signal_handler
);
/* Start Mongoose */
/* Start Mongoose */
ctx
=
mg_start
(
&
mongoose_callback
,
NULL
,
(
const
char
**
)
options
);
memset
(
&
callbacks
,
0
,
sizeof
(
callbacks
));
callbacks
.
log_message
=
&
log_message
;
ctx
=
mg_start
(
&
callbacks
,
NULL
,
(
const
char
**
)
options
);
for
(
i
=
0
;
options
[
i
]
!=
NULL
;
i
++
)
{
for
(
i
=
0
;
options
[
i
]
!=
NULL
;
i
++
)
{
free
(
options
[
i
]);
free
(
options
[
i
]);
}
}
...
...
mongoose.c
View file @
ee55d38b
...
@@ -466,11 +466,11 @@ static const char *config_options[] = {
...
@@ -466,11 +466,11 @@ static const char *config_options[] = {
#define ENTRIES_PER_CONFIG_OPTION 3
#define ENTRIES_PER_CONFIG_OPTION 3
struct
mg_context
{
struct
mg_context
{
volatile
int
stop_flag
;
// Should we stop event loop
volatile
int
stop_flag
;
// Should we stop event loop
SSL_CTX
*
ssl_ctx
;
// SSL context
SSL_CTX
*
ssl_ctx
;
// SSL context
char
*
config
[
NUM_OPTIONS
];
// Mongoose configuration parameters
char
*
config
[
NUM_OPTIONS
];
// Mongoose configuration parameters
mg_callback_t
user_callback
;
// User-defined callback function
struct
mg_callbacks
callbacks
;
// User-defined callback function
void
*
user_data
;
// User-defined data
void
*
user_data
;
// User-defined data
struct
socket
*
listening_sockets
;
struct
socket
*
listening_sockets
;
int
num_listening_sockets
;
int
num_listening_sockets
;
...
@@ -512,20 +512,12 @@ const char **mg_get_valid_option_names(void) {
...
@@ -512,20 +512,12 @@ const char **mg_get_valid_option_names(void) {
return
config_options
;
return
config_options
;
}
}
static
void
*
call_user
(
struct
mg_connection
*
conn
,
enum
mg_event
event
)
{
if
(
conn
!=
NULL
&&
conn
->
ctx
!=
NULL
)
{
conn
->
request_info
.
user_data
=
conn
->
ctx
->
user_data
;
}
return
conn
==
NULL
||
conn
->
ctx
==
NULL
||
conn
->
ctx
->
user_callback
==
NULL
?
NULL
:
conn
->
ctx
->
user_callback
(
event
,
conn
);
}
static
int
is_file_in_memory
(
struct
mg_connection
*
conn
,
const
char
*
path
,
static
int
is_file_in_memory
(
struct
mg_connection
*
conn
,
const
char
*
path
,
struct
file
*
filep
)
{
struct
file
*
filep
)
{
conn
->
request_info
.
ev_data
=
(
void
*
)
path
;
size_t
size
=
0
;
if
((
filep
->
membuf
=
call_user
(
conn
,
MG_OPEN_FILE
))
!=
NULL
)
{
filep
->
membuf
=
conn
->
ctx
->
callbacks
.
open_file
==
NULL
?
NULL
:
filep
->
size
=
(
long
)
conn
->
request_info
.
ev_data
;
conn
->
ctx
->
callbacks
.
open_file
(
conn
,
path
,
&
size
)
;
}
filep
->
size
=
size
;
return
filep
->
membuf
!=
NULL
;
return
filep
->
membuf
!=
NULL
;
}
}
...
@@ -610,8 +602,8 @@ static void cry(struct mg_connection *conn, const char *fmt, ...) {
...
@@ -610,8 +602,8 @@ static void cry(struct mg_connection *conn, const char *fmt, ...) {
// Do not lock when getting the callback value, here and below.
// Do not lock when getting the callback value, here and below.
// I suppose this is fine, since function cannot disappear in the
// I suppose this is fine, since function cannot disappear in the
// same way string option can.
// same way string option can.
conn
->
request_info
.
ev_data
=
buf
;
if
(
conn
->
ctx
->
callbacks
.
log_message
==
NULL
||
if
(
call_user
(
conn
,
MG_EVENT_LOG
)
==
NULL
)
{
conn
->
ctx
->
callbacks
.
log_message
(
conn
,
buf
)
==
0
)
{
fp
=
conn
->
ctx
==
NULL
||
conn
->
ctx
->
config
[
ERROR_LOG_FILE
]
==
NULL
?
NULL
:
fp
=
conn
->
ctx
==
NULL
||
conn
->
ctx
->
config
[
ERROR_LOG_FILE
]
==
NULL
?
NULL
:
fopen
(
conn
->
ctx
->
config
[
ERROR_LOG_FILE
],
"a+"
);
fopen
(
conn
->
ctx
->
config
[
ERROR_LOG_FILE
],
"a+"
);
...
@@ -634,7 +626,6 @@ static void cry(struct mg_connection *conn, const char *fmt, ...) {
...
@@ -634,7 +626,6 @@ static void cry(struct mg_connection *conn, const char *fmt, ...) {
fclose
(
fp
);
fclose
(
fp
);
}
}
}
}
conn
->
request_info
.
ev_data
=
NULL
;
}
}
// Return fake connection structure. Used for logging, if connection
// Return fake connection structure. Used for logging, if connection
...
@@ -917,31 +908,27 @@ static void send_http_error(struct mg_connection *conn, int status,
...
@@ -917,31 +908,27 @@ static void send_http_error(struct mg_connection *conn, int status,
const
char
*
reason
,
const
char
*
fmt
,
...)
{
const
char
*
reason
,
const
char
*
fmt
,
...)
{
char
buf
[
MG_BUF_LEN
];
char
buf
[
MG_BUF_LEN
];
va_list
ap
;
va_list
ap
;
int
len
;
int
len
=
0
;
conn
->
status_code
=
status
;
conn
->
status_code
=
status
;
conn
->
request_info
.
ev_data
=
(
void
*
)
(
long
)
status
;
buf
[
0
]
=
'\0'
;
if
(
call_user
(
conn
,
MG_HTTP_ERROR
)
==
NULL
)
{
buf
[
0
]
=
'\0'
;
len
=
0
;
// Errors 1xx, 204 and 304 MUST NOT send a body
if
(
status
>
199
&&
status
!=
204
&&
status
!=
304
)
{
len
=
mg_snprintf
(
conn
,
buf
,
sizeof
(
buf
),
"Error %d: %s"
,
status
,
reason
);
buf
[
len
++
]
=
'\n'
;
va_start
(
ap
,
fmt
);
len
+=
mg_vsnprintf
(
conn
,
buf
+
len
,
sizeof
(
buf
)
-
len
,
fmt
,
ap
);
va_end
(
ap
);
}
DEBUG_TRACE
((
"[%s]"
,
buf
));
mg_printf
(
conn
,
"HTTP/1.1 %d %s
\r\n
"
// Errors 1xx, 204 and 304 MUST NOT send a body
"Content-Length: %d
\r\n
"
if
(
status
>
199
&&
status
!=
204
&&
status
!=
304
)
{
"Connection: %s
\r\n\r\n
"
,
status
,
reason
,
len
,
len
=
mg_snprintf
(
conn
,
buf
,
sizeof
(
buf
),
"Error %d: %s"
,
status
,
reason
);
suggest_connection_header
(
conn
));
buf
[
len
++
]
=
'\n'
;
conn
->
num_bytes_sent
+=
mg_printf
(
conn
,
"%s"
,
buf
);
va_start
(
ap
,
fmt
);
len
+=
mg_vsnprintf
(
conn
,
buf
+
len
,
sizeof
(
buf
)
-
len
,
fmt
,
ap
);
va_end
(
ap
);
}
}
DEBUG_TRACE
((
"[%s]"
,
buf
));
mg_printf
(
conn
,
"HTTP/1.1 %d %s
\r\n
"
"Content-Length: %d
\r\n
"
"Connection: %s
\r\n\r\n
"
,
status
,
reason
,
len
,
suggest_connection_header
(
conn
));
conn
->
num_bytes_sent
+=
mg_printf
(
conn
,
"%s"
,
buf
);
}
}
#if defined(_WIN32) && !defined(__SYMBIAN32__)
#if defined(_WIN32) && !defined(__SYMBIAN32__)
...
@@ -2609,7 +2596,7 @@ static int scan_directory(struct mg_connection *conn, const char *dir,
...
@@ -2609,7 +2596,7 @@ static int scan_directory(struct mg_connection *conn, const char *dir,
// print_dir_entry(). memset is required only if mg_stat()
// print_dir_entry(). memset is required only if mg_stat()
// fails. For more details, see
// fails. For more details, see
// http://code.google.com/p/mongoose/issues/detail?id=79
// http://code.google.com/p/mongoose/issues/detail?id=79
// mg_stat will memset the whole struct file with zeroes.
memset
(
&
de
.
file
,
0
,
sizeof
(
de
.
file
));
mg_stat
(
conn
,
path
,
&
de
.
file
);
mg_stat
(
conn
,
path
,
&
de
.
file
);
de
.
file_name
=
dp
->
d_name
;
de
.
file_name
=
dp
->
d_name
;
...
@@ -3797,7 +3784,8 @@ static void read_websocket(struct mg_connection *conn) {
...
@@ -3797,7 +3784,8 @@ static void read_websocket(struct mg_connection *conn) {
}
}
if
(
conn
->
content_len
>
0
)
{
if
(
conn
->
content_len
>
0
)
{
if
(
call_user
(
conn
,
MG_WEBSOCKET_MESSAGE
)
!=
NULL
)
{
if
(
conn
->
ctx
->
callbacks
.
websocket_data
!=
NULL
&&
conn
->
ctx
->
callbacks
.
websocket_data
(
conn
)
==
0
)
{
break
;
// Callback signalled to exit
break
;
// Callback signalled to exit
}
}
discard_len
=
conn
->
content_len
>
body_len
?
discard_len
=
conn
->
content_len
>
body_len
?
...
@@ -3819,13 +3807,15 @@ static void read_websocket(struct mg_connection *conn) {
...
@@ -3819,13 +3807,15 @@ static void read_websocket(struct mg_connection *conn) {
static
void
handle_websocket_request
(
struct
mg_connection
*
conn
)
{
static
void
handle_websocket_request
(
struct
mg_connection
*
conn
)
{
if
(
strcmp
(
mg_get_header
(
conn
,
"Sec-WebSocket-Version"
),
"13"
)
!=
0
)
{
if
(
strcmp
(
mg_get_header
(
conn
,
"Sec-WebSocket-Version"
),
"13"
)
!=
0
)
{
send_http_error
(
conn
,
426
,
"Upgrade Required"
,
"%s"
,
"Upgrade Required"
);
send_http_error
(
conn
,
426
,
"Upgrade Required"
,
"%s"
,
"Upgrade Required"
);
}
else
if
(
call_user
(
conn
,
MG_WEBSOCKET_CONNECT
)
!=
NULL
)
{
}
else
if
(
conn
->
ctx
->
callbacks
.
websocket_connect
!=
NULL
&&
// Callback has returned non-NULL, do not proceed with handshake
conn
->
ctx
->
callbacks
.
websocket_connect
(
conn
)
!=
0
)
{
// Callback has returned non-zero, do not proceed with handshake
}
else
{
}
else
{
send_websocket_handshake
(
conn
);
send_websocket_handshake
(
conn
);
call_user
(
conn
,
MG_WEBSOCKET_READY
);
if
(
conn
->
ctx
->
callbacks
.
websocket_ready
!=
NULL
)
{
conn
->
ctx
->
callbacks
.
websocket_ready
(
conn
);
}
read_websocket
(
conn
);
read_websocket
(
conn
);
call_user
(
conn
,
MG_WEBSOCKET_CLOSE
);
}
}
}
}
...
@@ -4035,8 +4025,9 @@ static void handle_lsp_request(struct mg_connection *conn, const char *path,
...
@@ -4035,8 +4025,9 @@ static void handle_lsp_request(struct mg_connection *conn, const char *path,
}
else
{
}
else
{
// We're not sending HTTP headers here, Lua page must do it.
// We're not sending HTTP headers here, Lua page must do it.
prepare_lua_environment
(
conn
,
L
);
prepare_lua_environment
(
conn
,
L
);
conn
->
request_info
.
ev_data
=
L
;
if
(
conn
->
ctx
->
callbacks
.
init_lua
!=
NULL
)
{
call_user
(
conn
,
MG_INIT_LUA
);
conn
->
ctx
->
callbacks
.
init_lua
(
conn
,
L
);
}
lsp
(
conn
,
filep
->
membuf
==
NULL
?
p
:
filep
->
membuf
,
filep
->
size
,
L
);
lsp
(
conn
,
filep
->
membuf
==
NULL
?
p
:
filep
->
membuf
,
filep
->
size
,
L
);
}
}
...
@@ -4135,8 +4126,9 @@ int mg_upload(struct mg_connection *conn, const char *destination_dir) {
...
@@ -4135,8 +4126,9 @@ int mg_upload(struct mg_connection *conn, const char *destination_dir) {
fwrite
(
buf
,
1
,
i
,
fp
);
fwrite
(
buf
,
1
,
i
,
fp
);
fflush
(
fp
);
fflush
(
fp
);
num_uploaded_files
++
;
num_uploaded_files
++
;
conn
->
request_info
.
ev_data
=
(
void
*
)
path
;
if
(
conn
->
ctx
->
callbacks
.
upload
!=
NULL
)
{
call_user
(
conn
,
MG_UPLOAD
);
conn
->
ctx
->
callbacks
.
upload
(
conn
,
path
);
}
memmove
(
buf
,
&
buf
[
i
+
bl
],
len
-
(
i
+
bl
));
memmove
(
buf
,
&
buf
[
i
+
bl
],
len
-
(
i
+
bl
));
len
-=
i
+
bl
;
len
-=
i
+
bl
;
break
;
break
;
...
@@ -4203,7 +4195,8 @@ static void handle_request(struct mg_connection *conn) {
...
@@ -4203,7 +4195,8 @@ static void handle_request(struct mg_connection *conn) {
get_remote_ip
(
conn
),
ri
->
uri
);
get_remote_ip
(
conn
),
ri
->
uri
);
DEBUG_TRACE
((
"%s"
,
ri
->
uri
));
DEBUG_TRACE
((
"%s"
,
ri
->
uri
));
if
(
call_user
(
conn
,
MG_NEW_REQUEST
)
!=
NULL
)
{
if
(
conn
->
ctx
->
callbacks
.
begin_request
!=
NULL
&&
conn
->
ctx
->
callbacks
.
begin_request
(
conn
))
{
// Do nothing, callback has served the request
// Do nothing, callback has served the request
}
else
if
(
!
conn
->
client
.
is_ssl
&&
conn
->
client
.
ssl_redir
&&
}
else
if
(
!
conn
->
client
.
is_ssl
&&
conn
->
client
.
ssl_redir
&&
(
ssl_index
=
get_first_ssl_listener_index
(
conn
->
ctx
))
>
-
1
)
{
(
ssl_index
=
get_first_ssl_listener_index
(
conn
->
ctx
))
>
-
1
)
{
...
@@ -4550,8 +4543,8 @@ static int set_ssl_option(struct mg_context *ctx) {
...
@@ -4550,8 +4543,8 @@ static int set_ssl_option(struct mg_context *ctx) {
// If user callback returned non-NULL, that means that user callback has
// If user callback returned non-NULL, that means that user callback has
// set up certificate itself. In this case, skip sertificate setting.
// set up certificate itself. In this case, skip sertificate setting.
fc
(
ctx
)
->
request_info
.
ev_data
=
ctx
->
ssl_ctx
;
if
((
ctx
->
callbacks
.
init_ssl
==
NULL
||
if
(
call_user
(
fc
(
ctx
),
MG_INIT_SSL
)
==
NULL
&&
!
ctx
->
callbacks
.
init_ssl
(
ctx
->
ssl_ctx
))
&&
(
SSL_CTX_use_certificate_file
(
ctx
->
ssl_ctx
,
pem
,
1
)
==
0
||
(
SSL_CTX_use_certificate_file
(
ctx
->
ssl_ctx
,
pem
,
1
)
==
0
||
SSL_CTX_use_PrivateKey_file
(
ctx
->
ssl_ctx
,
pem
,
1
)
==
0
))
{
SSL_CTX_use_PrivateKey_file
(
ctx
->
ssl_ctx
,
pem
,
1
)
==
0
))
{
cry
(
fc
(
ctx
),
"%s: cannot open %s: %s"
,
__func__
,
pem
,
ssl_error
());
cry
(
fc
(
ctx
),
"%s: cannot open %s: %s"
,
__func__
,
pem
,
ssl_error
());
...
@@ -4608,7 +4601,7 @@ static int set_acl_option(struct mg_context *ctx) {
...
@@ -4608,7 +4601,7 @@ static int set_acl_option(struct mg_context *ctx) {
}
}
static
void
reset_per_request_attributes
(
struct
mg_connection
*
conn
)
{
static
void
reset_per_request_attributes
(
struct
mg_connection
*
conn
)
{
conn
->
path_info
=
conn
->
request_info
.
ev_data
=
NULL
;
conn
->
path_info
=
NULL
;
conn
->
num_bytes_sent
=
conn
->
consumed_content
=
0
;
conn
->
num_bytes_sent
=
conn
->
consumed_content
=
0
;
conn
->
status_code
=
-
1
;
conn
->
status_code
=
-
1
;
conn
->
must_close
=
conn
->
request_len
=
conn
->
throttle
=
0
;
conn
->
must_close
=
conn
->
request_len
=
conn
->
throttle
=
0
;
...
@@ -4811,8 +4804,9 @@ static void process_new_connection(struct mg_connection *conn) {
...
@@ -4811,8 +4804,9 @@ static void process_new_connection(struct mg_connection *conn) {
if
(
ebuf
[
0
]
==
'\0'
)
{
if
(
ebuf
[
0
]
==
'\0'
)
{
handle_request
(
conn
);
handle_request
(
conn
);
conn
->
request_info
.
ev_data
=
(
void
*
)
(
long
)
conn
->
status_code
;
if
(
conn
->
ctx
->
callbacks
.
end_request
!=
NULL
)
{
call_user
(
conn
,
MG_REQUEST_COMPLETE
);
conn
->
ctx
->
callbacks
.
end_request
(
conn
,
conn
->
status_code
);
}
log_access
(
conn
);
log_access
(
conn
);
}
}
if
(
ri
->
remote_user
!=
NULL
)
{
if
(
ri
->
remote_user
!=
NULL
)
{
...
@@ -5087,7 +5081,8 @@ void mg_stop(struct mg_context *ctx) {
...
@@ -5087,7 +5081,8 @@ void mg_stop(struct mg_context *ctx) {
#endif // _WIN32
#endif // _WIN32
}
}
struct
mg_context
*
mg_start
(
mg_callback_t
user_callback
,
void
*
user_data
,
struct
mg_context
*
mg_start
(
const
struct
mg_callbacks
*
callbacks
,
void
*
user_data
,
const
char
**
options
)
{
const
char
**
options
)
{
struct
mg_context
*
ctx
;
struct
mg_context
*
ctx
;
const
char
*
name
,
*
value
,
*
default_value
;
const
char
*
name
,
*
value
,
*
default_value
;
...
@@ -5104,7 +5099,7 @@ struct mg_context *mg_start(mg_callback_t user_callback, void *user_data,
...
@@ -5104,7 +5099,7 @@ struct mg_context *mg_start(mg_callback_t user_callback, void *user_data,
if
((
ctx
=
(
struct
mg_context
*
)
calloc
(
1
,
sizeof
(
*
ctx
)))
==
NULL
)
{
if
((
ctx
=
(
struct
mg_context
*
)
calloc
(
1
,
sizeof
(
*
ctx
)))
==
NULL
)
{
return
NULL
;
return
NULL
;
}
}
ctx
->
user_callback
=
user_callback
;
ctx
->
callbacks
=
*
callbacks
;
ctx
->
user_data
=
user_data
;
ctx
->
user_data
=
user_data
;
while
(
options
&&
(
name
=
*
options
++
)
!=
NULL
)
{
while
(
options
&&
(
name
=
*
options
++
)
!=
NULL
)
{
...
...
mongoose.h
View file @
ee55d38b
...
@@ -42,13 +42,13 @@ struct mg_request_info {
...
@@ -42,13 +42,13 @@ struct mg_request_info {
long
remote_ip
;
// Client's IP address
long
remote_ip
;
// Client's IP address
int
remote_port
;
// Client's port
int
remote_port
;
// Client's port
int
is_ssl
;
// 1 if SSL-ed, 0 if not
int
is_ssl
;
// 1 if SSL-ed, 0 if not
int
num_headers
;
// Number of headers
void
*
user_data
;
// User data pointer passed to mg_start()
int
num_headers
;
// Number of HTTP headers
struct
mg_header
{
struct
mg_header
{
const
char
*
name
;
// HTTP header name
const
char
*
name
;
// HTTP header name
const
char
*
value
;
// HTTP header value
const
char
*
value
;
// HTTP header value
}
http_headers
[
64
];
// Maximum 64 headers
}
http_headers
[
64
];
// Maximum 64 headers
void
*
user_data
;
// User data pointer passed to mg_start()
void
*
ev_data
;
// Event-specific data pointer
};
};
...
@@ -56,126 +56,23 @@ struct mg_request_info {
...
@@ -56,126 +56,23 @@ struct mg_request_info {
// which callbacks to invoke. For detailed description, see
// which callbacks to invoke. For detailed description, see
// https://github.com/valenok/mongoose/blob/master/UserManual.md
// https://github.com/valenok/mongoose/blob/master/UserManual.md
struct
mg_callbacks
{
struct
mg_callbacks
{
int
(
*
request_star
t
)(
struct
mg_connection
*
);
int
(
*
begin_reques
t
)(
struct
mg_connection
*
);
void
(
*
request_done
)(
struct
mg_connection
*
,
int
reply_status_code
);
void
(
*
end_request
)(
const
struct
mg_connection
*
,
int
reply_status_code
);
int
(
*
log_message
)(
struct
mg_connection
*
,
const
char
*
message
);
int
(
*
log_message
)(
const
struct
mg_connection
*
,
const
char
*
message
);
int
(
*
init_ssl
)(
void
*
ssl_context
);
int
(
*
init_ssl
)(
void
*
ssl_context
);
void
(
*
websocket_connect
)(
struct
mg_connection
*
);
int
(
*
websocket_connect
)(
const
struct
mg_connection
*
);
void
(
*
websocket_ready
)(
struct
mg_connection
*
);
void
(
*
websocket_ready
)(
struct
mg_connection
*
);
int
(
*
websocket_data
)(
struct
mg_connection
*
);
int
(
*
websocket_data
)(
struct
mg_connection
*
);
void
(
*
websocket_close
)(
struct
mg_connection
*
);
const
char
*
(
*
open_file
)(
const
struct
mg_connection
*
,
void
(
*
open_file
)(
struct
mg_connection
*
,
char
**
data
,
size_t
*
data_len
);
const
char
*
path
,
size_t
*
data_len
);
void
(
*
init_lua
)(
struct
mg_connection
*
,
void
*
lua_context
);
void
(
*
init_lua
)(
struct
mg_connection
*
,
void
*
lua_context
);
void
(
*
upload
)(
struct
mg_connection
*
,
const
char
*
file_name
);
void
(
*
upload
)(
struct
mg_connection
*
,
const
char
*
file_name
);
};
};
// Various events on which user-defined callback function is called by Mongoose.
enum
mg_event
{
// New HTTP request has arrived from the client.
// If callback returns non-NULL, Mongoose stops handling current request.
// ev_data contains NULL.
MG_NEW_REQUEST
,
// Mongoose has finished handling the request.
// Callback return value is ignored.
// ev_data contains integer HTTP status code:
// int http_reply_status_code = (long) request_info->ev_data;
MG_REQUEST_COMPLETE
,
// HTTP error must be returned to the client.
// If callback returns non-NULL, Mongoose stops handling error.
// ev_data contains HTTP error code:
// int http_reply_status_code = (long) request_info->ev_data;
MG_HTTP_ERROR
,
// Mongoose logs a message.
// If callback returns non-NULL, Mongoose stops handling that event.
// ev_data contains a message to be logged:
// const char *log_message = request_info->ev_data;
MG_EVENT_LOG
,
// SSL initialization, sent before certificate setup.
// If callback returns non-NULL, Mongoose does not set up certificates.
// ev_data contains server's OpenSSL context:
// SSL_CTX *ssl_context = request_info->ev_data;
MG_INIT_SSL
,
// Sent on HTTP connect, before websocket handshake.
// If user callback returns NULL, then mongoose proceeds
// with handshake, otherwise it closes the connection.
// ev_data contains NULL.
MG_WEBSOCKET_CONNECT
,
// Handshake has been successfully completed.
// Callback's return value is ignored.
// ev_data contains NULL.
MG_WEBSOCKET_READY
,
// Incoming message from the client, data could be read with mg_read().
// If user callback returns non-NULL, mongoose closes the websocket.
// ev_data contains NULL.
MG_WEBSOCKET_MESSAGE
,
// Client has closed the connection.
// Callback's return value is ignored.
// ev_data contains NULL.
MG_WEBSOCKET_CLOSE
,
// Mongoose tries to open file.
// If callback returns non-NULL, Mongoose will not try to open it, but
// will use the returned value as a pointer to the file data. This allows
// for example to serve files from memory.
// ev_data contains file path, including document root path.
// Upon return, ev_data should return file size, which should be a long int.
//
// const char *file_name = request_info->ev_data;
// if (strcmp(file_name, "foo.txt") == 0) {
// request_info->ev_data = (void *) (long) 4;
// return "data";
// }
// return NULL;
//
// Note that this even is sent multiple times during one request. Each
// time mongoose tries to open or stat the file, this event is sent, e.g.
// for opening .htpasswd file, stat-ting requested file, opening requested
// file, etc.
MG_OPEN_FILE
,
// Mongoose initializes Lua server page. Sent only if Lua support is enabled.
// Callback's return value is ignored.
// ev_data contains lua_State pointer.
MG_INIT_LUA
,
// Mongoose has uploaded file to a temporary directory.
// Callback's return value is ignored.
// ev_data contains NUL-terminated file name.
MG_UPLOAD
,
};
// Prototype for the user-defined function. Mongoose calls this function
// on every MG_* event.
//
// Parameters:
// event: which event has been triggered.
// conn: opaque connection handler. Could be used to read, write data to the
// client, etc. See functions below that have "mg_connection *" arg.
//
// Return:
// If handler returns non-NULL, that means that handler has processed the
// request by sending appropriate HTTP reply to the client. Mongoose treats
// the request as served.
// If handler returns NULL, that means that handler has not processed
// the request. Handler must not send any data to the client in this case.
// Mongoose proceeds with request handling as if nothing happened.
typedef
void
*
(
*
mg_callback_t
)(
enum
mg_event
event
,
struct
mg_connection
*
conn
);
// Start web server.
// Start web server.
//
//
// Parameters:
// Parameters:
// callback
: user defined event handling function or NULL
.
// callback
s: mg_callbacks structure with user-defined callbacks
.
// options: NULL terminated list of option_name, option_value pairs that
// options: NULL terminated list of option_name, option_value pairs that
// specify Mongoose configuration parameters.
// specify Mongoose configuration parameters.
//
//
...
@@ -197,8 +94,9 @@ typedef void *(*mg_callback_t)(enum mg_event event, struct mg_connection *conn);
...
@@ -197,8 +94,9 @@ typedef void *(*mg_callback_t)(enum mg_event event, struct mg_connection *conn);
//
//
// Return:
// Return:
// web server context, or NULL on error.
// web server context, or NULL on error.
struct
mg_context
*
mg_start
(
mg_callback_t
callback
,
void
*
user_data
,
struct
mg_context
*
mg_start
(
const
struct
mg_callbacks
*
callbacks
,
const
char
**
options
);
void
*
user_data
,
const
char
**
configuration_options
);
// Stop the web server.
// Stop the web server.
...
...
test/test.pl
View file @
ee55d38b
...
@@ -426,7 +426,7 @@ unless (scalar(@ARGV) > 0 and $ARGV[0] eq "basic_tests") {
...
@@ -426,7 +426,7 @@ unless (scalar(@ARGV) > 0 and $ARGV[0] eq "basic_tests") {
do_PUT_test
();
do_PUT_test
();
kill_spawned_child
();
kill_spawned_child
();
do_unit_test
();
do_unit_test
();
do_embedded_test
();
#
do_embedded_test();
}
}
sub
do_PUT_test
{
sub
do_PUT_test
{
...
...
test/unit_test.c
View file @
ee55d38b
...
@@ -189,44 +189,61 @@ static const char *inmemory_file_data = "hi there";
...
@@ -189,44 +189,61 @@ static const char *inmemory_file_data = "hi there";
static
const
char
*
upload_filename
=
"upload_test.txt"
;
static
const
char
*
upload_filename
=
"upload_test.txt"
;
static
const
char
*
upload_ok_message
=
"upload successful"
;
static
const
char
*
upload_ok_message
=
"upload successful"
;
static
void
*
event_handler
(
enum
mg_event
event
,
struct
mg_connection
*
conn
)
{
static
const
char
*
open_file_cb
(
const
struct
mg_connection
*
conn
,
const
struct
mg_request_info
*
request_info
=
mg_get_request_info
(
conn
);
const
char
*
path
,
size_t
*
size
)
{
(
void
)
conn
;
if
(
!
strcmp
(
path
,
"./blah"
))
{
*
size
=
strlen
(
inmemory_file_data
);
return
inmemory_file_data
;
}
return
NULL
;
}
static
void
upload_cb
(
struct
mg_connection
*
conn
,
const
char
*
path
)
{
char
*
p1
,
*
p2
;
int
len1
,
len2
;
ASSERT
(
!
strcmp
(
path
,
"./upload_test.txt"
));
ASSERT
((
p1
=
read_file
(
"mongoose.c"
,
&
len1
))
!=
NULL
);
ASSERT
((
p2
=
read_file
(
path
,
&
len2
))
!=
NULL
);
ASSERT
(
len1
==
len2
);
ASSERT
(
memcmp
(
p1
,
p2
,
len1
)
==
0
);
free
(
p1
),
free
(
p2
);
remove
(
upload_filename
);
mg_printf
(
conn
,
"HTTP/1.0 200 OK
\r\n
Content-Length: %d
\r\n\r\n
%s"
,
(
int
)
strlen
(
upload_ok_message
),
upload_ok_message
);
}
static
int
begin_request_handler_cb
(
struct
mg_connection
*
conn
)
{
const
struct
mg_request_info
*
ri
=
mg_get_request_info
(
conn
);
if
(
event
==
MG_NEW_REQUEST
&&
!
strcmp
(
request_info
->
uri
,
"/data"
))
{
if
(
!
strcmp
(
ri
->
uri
,
"/data"
))
{
mg_printf
(
conn
,
"HTTP/1.1 200 OK
\r\n
"
mg_printf
(
conn
,
"HTTP/1.1 200 OK
\r\n
"
"Content-Length: %d
\r\n
"
"Content-Length: %d
\r\n
"
"Content-Type: text/plain
\r\n\r\n
"
"Content-Type: text/plain
\r\n\r\n
"
"%s"
,
(
int
)
strlen
(
fetch_data
),
fetch_data
);
"%s"
,
(
int
)
strlen
(
fetch_data
),
fetch_data
);
return
""
;
return
1
;
}
else
if
(
event
==
MG_NEW_REQUEST
&&
!
strcmp
(
request_info
->
uri
,
"/upload"
))
{
}
if
(
!
strcmp
(
ri
->
uri
,
"/upload"
))
{
ASSERT
(
mg_upload
(
conn
,
"."
)
==
1
);
ASSERT
(
mg_upload
(
conn
,
"."
)
==
1
);
}
else
if
(
event
==
MG_OPEN_FILE
)
{
const
char
*
path
=
request_info
->
ev_data
;
if
(
strcmp
(
path
,
"./blah"
)
==
0
)
{
mg_get_request_info
(
conn
)
->
ev_data
=
(
void
*
)
(
long
)
strlen
(
inmemory_file_data
);
return
(
void
*
)
inmemory_file_data
;
}
}
else
if
(
event
==
MG_EVENT_LOG
)
{
}
else
if
(
event
==
MG_UPLOAD
)
{
char
*
p1
,
*
p2
;
int
len1
,
len2
;
ASSERT
(
!
strcmp
((
char
*
)
request_info
->
ev_data
,
"./upload_test.txt"
));
ASSERT
((
p1
=
read_file
(
"mongoose.c"
,
&
len1
))
!=
NULL
);
ASSERT
((
p2
=
read_file
(
upload_filename
,
&
len2
))
!=
NULL
);
ASSERT
(
len1
==
len2
);
ASSERT
(
memcmp
(
p1
,
p2
,
len1
)
==
0
);
free
(
p1
),
free
(
p2
);
remove
(
upload_filename
);
mg_printf
(
conn
,
"HTTP/1.0 200 OK
\r\n
Content-Length: %d
\r\n\r\n
%s"
,
(
int
)
strlen
(
upload_ok_message
),
upload_ok_message
);
}
}
return
NULL
;
return
0
;
}
static
int
log_message_cb
(
const
struct
mg_connection
*
conn
,
const
char
*
msg
)
{
(
void
)
conn
;
printf
(
"%s
\n
"
,
msg
);
return
0
;
}
}
static
const
struct
mg_callbacks
CALLBACKS
=
{
&
begin_request_handler_cb
,
NULL
,
&
log_message_cb
,
NULL
,
NULL
,
NULL
,
NULL
,
&
open_file_cb
,
NULL
,
&
upload_cb
};
static
const
char
*
OPTIONS
[]
=
{
static
const
char
*
OPTIONS
[]
=
{
"document_root"
,
"."
,
"document_root"
,
"."
,
"listening_ports"
,
LISTENING_ADDR
,
"listening_ports"
,
LISTENING_ADDR
,
...
@@ -252,7 +269,7 @@ static void test_mg_download(void) {
...
@@ -252,7 +269,7 @@ static void test_mg_download(void) {
struct
mg_connection
*
conn
;
struct
mg_connection
*
conn
;
struct
mg_context
*
ctx
;
struct
mg_context
*
ctx
;
ASSERT
((
ctx
=
mg_start
(
event_handler
,
NULL
,
OPTIONS
))
!=
NULL
);
ASSERT
((
ctx
=
mg_start
(
&
CALLBACKS
,
NULL
,
OPTIONS
))
!=
NULL
);
ASSERT
(
mg_download
(
NULL
,
port
,
0
,
ebuf
,
sizeof
(
ebuf
),
"%s"
,
""
)
==
NULL
);
ASSERT
(
mg_download
(
NULL
,
port
,
0
,
ebuf
,
sizeof
(
ebuf
),
"%s"
,
""
)
==
NULL
);
ASSERT
(
mg_download
(
"localhost"
,
0
,
0
,
ebuf
,
sizeof
(
ebuf
),
"%s"
,
""
)
==
NULL
);
ASSERT
(
mg_download
(
"localhost"
,
0
,
0
,
ebuf
,
sizeof
(
ebuf
),
"%s"
,
""
)
==
NULL
);
...
@@ -323,7 +340,7 @@ static void test_mg_upload(void) {
...
@@ -323,7 +340,7 @@ static void test_mg_upload(void) {
char
ebuf
[
100
],
buf
[
20
],
*
file_data
,
*
post_data
=
NULL
;
char
ebuf
[
100
],
buf
[
20
],
*
file_data
,
*
post_data
=
NULL
;
int
file_len
,
post_data_len
;
int
file_len
,
post_data_len
;
ASSERT
((
ctx
=
mg_start
(
event_handler
,
NULL
,
OPTIONS
))
!=
NULL
);
ASSERT
((
ctx
=
mg_start
(
&
CALLBACKS
,
NULL
,
OPTIONS
))
!=
NULL
);
ASSERT
((
file_data
=
read_file
(
"mongoose.c"
,
&
file_len
))
!=
NULL
);
ASSERT
((
file_data
=
read_file
(
"mongoose.c"
,
&
file_len
))
!=
NULL
);
post_data_len
=
alloc_printf
(
&
post_data
,
0
,
post_data_len
=
alloc_printf
(
&
post_data
,
0
,
"--%s
\r\n
"
"--%s
\r\n
"
...
@@ -462,22 +479,6 @@ static void test_lua(void) {
...
@@ -462,22 +479,6 @@ static void test_lua(void) {
}
}
#endif
#endif
static
void
*
user_data_tester
(
enum
mg_event
event
,
struct
mg_connection
*
conn
)
{
struct
mg_request_info
*
ri
=
mg_get_request_info
(
conn
);
ASSERT
(
ri
->
user_data
==
(
void
*
)
123
);
ASSERT
(
event
==
MG_NEW_REQUEST
||
event
==
MG_INIT_SSL
);
return
NULL
;
}
static
void
test_user_data
(
void
)
{
struct
mg_context
*
ctx
;
ASSERT
((
ctx
=
mg_start
(
user_data_tester
,
(
void
*
)
123
,
OPTIONS
))
!=
NULL
);
ASSERT
(
ctx
->
user_data
==
(
void
*
)
123
);
call_user
(
fc
(
ctx
),
MG_NEW_REQUEST
);
mg_stop
(
ctx
);
}
static
void
test_mg_stat
(
void
)
{
static
void
test_mg_stat
(
void
)
{
static
struct
mg_context
ctx
;
static
struct
mg_context
ctx
;
struct
file
file
=
STRUCT_FILE_INITIALIZER
;
struct
file
file
=
STRUCT_FILE_INITIALIZER
;
...
@@ -529,7 +530,7 @@ static void test_request_replies(void) {
...
@@ -529,7 +530,7 @@ static void test_request_replies(void) {
{
NULL
,
NULL
},
{
NULL
,
NULL
},
};
};
ASSERT
((
ctx
=
mg_start
(
event_handler
,
NULL
,
OPTIONS
))
!=
NULL
);
ASSERT
((
ctx
=
mg_start
(
&
CALLBACKS
,
NULL
,
OPTIONS
))
!=
NULL
);
for
(
i
=
0
;
tests
[
i
].
request
!=
NULL
;
i
++
)
{
for
(
i
=
0
;
tests
[
i
].
request
!=
NULL
;
i
++
)
{
ASSERT
((
conn
=
mg_download
(
"localhost"
,
port
,
1
,
ebuf
,
sizeof
(
ebuf
),
"%s"
,
ASSERT
((
conn
=
mg_download
(
"localhost"
,
port
,
1
,
ebuf
,
sizeof
(
ebuf
),
"%s"
,
tests
[
i
].
request
))
!=
NULL
);
tests
[
i
].
request
))
!=
NULL
);
...
@@ -549,7 +550,6 @@ int __cdecl main(void) {
...
@@ -549,7 +550,6 @@ int __cdecl main(void) {
test_mg_get_var
();
test_mg_get_var
();
test_set_throttle
();
test_set_throttle
();
test_next_option
();
test_next_option
();
test_user_data
();
test_mg_stat
();
test_mg_stat
();
test_skip_quoted
();
test_skip_quoted
();
test_mg_upload
();
test_mg_upload
();
...
...
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