Compare commits

..
81 Commits
Author SHA1 Message Date
Sergey Lyubka 0804ce71d5 updated date on a manual page 2012-09-23 14:50:07 +01:00
Sergey Lyubka 2ffb558e30 nullify ssl_mutexes after free-ing them 2012-09-23 14:19:36 +01:00
Sergey Lyubka 05062be889 Fix for issue 257 2012-09-23 13:55:33 +01:00
Sergey Lyubka ba6c01e602 Fixed check_acl() 2012-09-23 13:50:36 +01:00
Sergey Lyubka dfc0f00478 Implement -T option, throttling functionality 2012-09-23 13:28:27 +01:00
Sergey Lyubka ecb2b0e53d Cleaner compilation for 16-bit targets 2012-09-23 02:13:53 +01:00
Sergey Lyubka ed74cd82f5 Added declarations for printf like functions 2012-09-23 01:35:59 +01:00
Sergey Lyubka d2be594262 defining PATH_MAX if not defined 2012-09-22 15:49:58 +01:00
Sergey Lyubka 1e632d3215 Removed "Content-Type: text/plain" header from send_http_error() response. 2012-09-22 15:21:21 +01:00
Sergey Lyubka 5642dfcf38 CGI handling on windows: constructing full path to the interpreter. enabling SO_REUSEADDR on listening socket. 2012-09-22 15:15:46 +01:00
Sergey Lyubka 4dff36ffde removed unused struct timespec 2012-09-22 13:36:24 +01:00
Sergey Lyubka 771ce9059c added 2012-09-22 13:31:10 +01:00
Sergey Lyubka e490b30c38 _mongoose.dll -> mongoose.dll 2012-09-22 13:15:05 +01:00
Sergey Lyubka f935ef832b _mongoose.dll -> mongoose.dll, _mongoose.so -> libbmongoose.so 2012-09-22 12:52:47 +01:00
Sergey Lyubka 79cdb77e5d Removed hard-coded CC value from Makefile 2012-09-22 12:27:20 +01:00
Sergey Lyubka ff0c2d3f91 Added unit test for mg_get_var 2012-09-22 12:22:30 +01:00
Sergey Lyubka 6f9901b65c config file parsing: allow blank lines 2012-09-22 11:29:50 +01:00
Sergey Lyubka bce3a85702 #including winsock2 and ws2tcpip headers by default on windows 2012-09-21 19:22:35 +01:00
Sergey Lyubka f741349d51 Fixed calculation of the number of leap days 2012-09-21 17:21:04 +01:00
Sergey Lyubka 25863b59a6 Sending MG_WEBSOCKET_CLOSE 2012-09-21 09:05:45 +01:00
Sergey Lyubka 72c861bb83 Python bindings synced 2012-09-21 09:05:12 +01:00
Sergey Lyubka 586574e176 Added #pragma comment(lib, "Ws2_32.lib") for win32 2012-09-21 09:03:47 +01:00
Sergey Lyubka 0f15954727 Skip SSL init if PEM file is not specified 2012-09-20 20:39:43 +01:00
Sergey Lyubka 167338f216 Using slash, "/" as the universal directory separator throughout the code 2012-09-20 18:20:41 +01:00
Sergey Lyubka d82f6b7607 Added /machine:IX86 to MSVC flags 2012-09-20 18:20:01 +01:00
Sergey Lyubka 614b219a27 Marking WRITE end of a pipe as closed in handle_cgi_request() 2012-09-20 17:22:22 +01:00
Sergey Lyubka 35cf8687df Merge pull request #32 from okigan/master
Compile on Windows
2012-09-20 08:45:31 -07:00
Sergey Lyubka d883b0f0f9 Prevent possible assert fail on windows in handle_cgi_request() 2012-09-20 15:11:38 +01:00
Sergey Lyubka 0b942aaaba Minor change for the win32 build 2012-09-20 14:55:09 +01:00
Sergey Lyubka 364235e7ae Squashed warning on windows 2012-09-20 14:54:51 +01:00
Sergey Lyubka ba1f2ced8e Cosmetic changes 2012-09-20 14:17:28 +01:00
Sergey Lyubka c4c34a8f4d Cosmetic changes 2012-09-20 14:17:04 +01:00
Sergey Lyubka a866f4e174 Cosmetic changes 2012-09-20 14:06:33 +01:00
Sergey Lyubka c5916814cd Added link to mongoose.c 2012-09-20 14:03:39 +01:00
Sergey Lyubka 349717ac0e removed stray new line 2012-09-20 14:02:33 +01:00
Sergey Lyubka 5d27766424 Added comment on the websocket example page 2012-09-20 14:01:45 +01:00
Sergey Lyubka 97668ba6c9 Updated README to reflect websocket and webdav support 2012-09-20 13:52:53 +01:00
Sergey Lyubka 98fb44f836 Refactored data buffering. Updated websocket example to have 2 message roundtrips. 2012-09-20 13:45:35 +01:00
Igor Okulist 2260c8ddc0 Merge branch 'master' of https://github.com/okigan/mongoose 2012-09-19 20:57:00 -07:00
Sergey Lyubka edffc46b98 removed -max_request_size option 2012-09-19 20:17:49 +01:00
Sergey Lyubka 7bd8cc3c0c added websocket example files 2012-09-19 12:31:19 +01:00
Sergey Lyubka 828f6cd7fe added link to the websocket example 2012-09-19 12:30:29 +01:00
Sergey Lyubka f9873eb87a Experimentl websocket support 2012-09-19 12:23:54 +01:00
Sergey Lyubka 358e4ffbf5 extra check in cry() for NULL context 2012-09-18 09:47:29 +01:00
Sergey Lyubka 9aad922983 added mg_get_ssl_context. passing fake connection to the MG_INIT_SSL event 2012-09-17 23:36:06 +01:00
Sergey Lyubka d9ab7af8b4 added comment in mongoose_callback 2012-09-17 23:35:11 +01:00
Sergey Lyubka 05b2a04267 moved status_code, user_data, log_message out of struct mg_request_info 2012-09-17 19:38:19 +01:00
Sergey Lyubka 4408083b4d removed ssl chain file option. restored context param in fc() call 2012-09-17 19:19:15 +01:00
Igor Okulist 4f01f101fc Compile on Win32 2012-09-15 20:40:28 -07:00
Sergey Lyubka d9f9911d9b removed max request size from options, moved to the #define 2012-09-15 10:58:50 +01:00
Sergey Lyubka 93b4562515 Added make target for upload example 2012-09-15 10:52:52 +01:00
Sergey Lyubka 0bb67e06c1 #define _XOPEN_SOURCE 600 only for linux 2012-09-15 10:51:35 +01:00
Sergey Lyubka 518b3aa726 Merge pull request #12 from nigels-com/master
Touch-ups for Regal build of mongoose
2012-09-14 03:28:20 -07:00
Sergey Lyubka 07f3554db3 Merge pull request #10 from nullable-type/master
Fix for issue 8
2012-09-14 02:30:50 -07:00
Sergey Lyubka acab70ee7c Updated readme to reference more examples 2012-09-14 10:27:43 +01:00
Sergey Lyubka c388bc2dd3 added upload example 2012-09-14 10:23:51 +01:00
Sergey Lyubka 8072b0a7d4 Do not report error if mg_printf() printed 0 bytes 2012-09-13 21:58:37 +01:00
Sergey Lyubka 3f4be595a6 Merge pull request #25 from siemens/master
Makefile for MinGW 4.7
2012-09-13 13:52:23 -07:00
Henrique Mendonça 5d11901af8 compile with MinGW 4.7 2012-09-13 19:39:02 +03:00
Sergey Lyubka 43953782f9 Do not require SSL, fix for issue 20 2012-09-06 10:06:30 +01:00
Sergey Lyubka 12e133a5e9 Merge branch 'master' of ssh://github.com/valenok/mongoose 2012-09-06 10:00:42 +01:00
Sergey Lyubka e92d4451ef fc() doesnt take ctx argument anymore 2012-09-06 09:54:39 +01:00
Sergey Lyubka fadb60d776 Merge pull request #17 from dnaeon/freebsd-fix
Fix building of mongoose under FreeBSD.
2012-09-04 02:26:19 -07:00
Marin Atanasov Nikolov 0521d78982 Fix building of mongoose under FreeBSD.
According to flockfile(3) under Linux you need only this:

    #define _XOPEN_SOURCE

* http://man7.org/linux/man-pages/man3/flockfile.3.html

This also fixes the build under FreeBSD.
2012-09-04 11:58:45 +03:00
Sergey Lyubka 3602d54a5b Better check for NULL in mg_connect() 2012-09-03 22:36:40 +01:00
Sergey Lyubka 8428f362c1 Added example for handling POST requests. 2012-08-31 09:24:34 +01:00
Nigel Stewart fafc9c6a20 Undefine WIN32_LEAN_AND_MEAN, if necessary.
Allow debug tracing to be disabled in debug-mode build by defining DEBUG_TRACE at compile-time.
2012-08-28 08:25:10 -05:00
test 66e088d843 Removed the test for a directory name with only a backslash, because this causes problems on windows. 2012-08-27 14:40:32 +02:00
Sergey Lyubka 4a760ad324 Initial version of readme 2012-08-25 22:48:14 +01:00
Sergey Lyubka c92d7c3bc8 Fix for Android: fread() might return < 0 2012-08-25 22:10:45 +01:00
Sergey Lyubka ee91109d9f Ger Hobbelt's fixes 2012-08-25 22:02:51 +01:00
Sergey Lyubka 30fe257691 Style fixes. Printing error message before fatal error. 2012-08-25 20:36:58 +01:00
Sergey Lyubka ab6f145e3e Update thread count on OOM error in worker_thread() 2012-08-25 20:24:09 +01:00
test 83dc425e25 Removed the test for a directory name with only a backslash, because this causes problems on windows. 2012-08-23 16:36:41 +02:00
Sergey Lyubka 001cd78b45 Styling changes plus extra GCC options to suppress certain warnings 2012-08-19 12:22:28 +01:00
Sergey Lyubka 3d3359910f Added printf format checking macros. Changed mg_printf() to allocate the buffer on heap if it does not fit the local one. 2012-08-19 12:08:33 +01:00
Sergey Lyubka ee8111e424 Unbreak backslash dir test 2012-08-19 12:06:35 +01:00
Sergey Lyubka 1861b1137b Merge pull request #5 from GerHobbelt/issue-g.c.370.get_request
backport of the relevant fix as per issue 370#c5: correct get_request under all circumstances
2012-08-18 13:06:13 -07:00
Ger Hobbelt ccf43fe3e3 backport of the relevant fix as per http://code.google.com/p/mongoose/issues/detail?id=370#c5 2012-08-18 21:44:29 +02:00
Sergey Lyubka 8b491d75b5 added const in mg_get_request_info() 2012-08-18 16:47:25 +01:00
Sergey Lyubka d70c18d692 3.2 -> 3.3 2012-08-17 21:42:25 +01:00
20 changed files with 1338 additions and 451 deletions

No files matched your search

+42 -41
View File
@@ -7,14 +7,14 @@ all:
@echo "make (linux|bsd|solaris|mac|windows|mingw)"
# Possible COPT values: (in brackets are rough numbers for 'gcc -O2' on i386)
# -DHAVE_MD5 - use system md5 library (-2kb)
# -DNDEBUG - strip off all debug code (-5kb)
# -DDEBUG - build debug version (very noisy) (+7kb)
# -DNO_CGI - disable CGI support (-5kb)
# -DNO_SSL - disable SSL functionality (-2kb)
# -DCONFIG_FILE=\"file\" - use `file' as the default config file
# -DHAVE_STRTOUI64 - use system strtoui64() function for strtoull()
# -DSSL_LIB=\"libssl.so.<version>\" - use system versioned SSL shared object
# -DHAVE_MD5 - use system md5 library (-2kb)
# -DNDEBUG - strip off all debug code (-5kb)
# -DDEBUG - build debug version (very noisy) (+7kb)
# -DNO_CGI - disable CGI support (-5kb)
# -DNO_SSL - disable SSL functionality (-2kb)
# -DCONFIG_FILE=\"file\" - use `file' as the default config file
# -DHAVE_STRTOUI64 - use system strtoui64() function for strtoull()
# -DSSL_LIB=\"libssl.so.<version>\" - use system versioned SSL shared object
# -DCRYPTO_LIB=\"libcrypto.so.<version>\" - use system versioned CRYPTO so
@@ -22,18 +22,19 @@ all:
### UNIX build: linux, bsd, mac, rtems
##########################################################################
CFLAGS = -W -Wall -std=c99 -pedantic -O2 $(COPT)
MAC_SHARED = -flat_namespace -bundle -undefined suppress
LINFLAGS = -ldl -pthread $(CFLAGS)
LIB = _$(PROG).so
#CC = g++
GCC_WARNS = -W -Wall -pedantic
# -Wno-missing-field-initializers -Wno-unused-parameter -Wno-format-zero-length -Wno-missing-braces
CFLAGS = -std=c99 -O2 $(GCC_WARNS) $(COPT)
MAC_SHARED = -flat_namespace -bundle -undefined suppress
LINFLAGS = -ldl -pthread $(CFLAGS)
LIB = lib$(PROG).so$(MONGOOSE_LIB_SUFFIX)
# Make sure that the compiler flags come last in the compilation string.
# If not so, this can break some on some Linux distros which use
# "-Wl,--as-needed" turned on by default in cc command.
# Also, this is turned in many other distros in static linkage builds.
linux:
$(CC) mongoose.c -shared -fPIC -fpic -o $(LIB) $(LINFLAGS)
$(CC) mongoose.c -shared -fPIC -fpic -o $(LIB) -Wl,-soname,$(LIB) $(LINFLAGS)
$(CC) mongoose.c main.c -o $(PROG) $(LINFLAGS)
bsd:
@@ -45,9 +46,9 @@ mac:
$(CC) mongoose.c main.c -pthread -o $(PROG) $(CFLAGS)
solaris:
gcc mongoose.c -pthread -lnsl \
$(CC) mongoose.c -pthread -lnsl \
-lsocket -fpic -fPIC -shared -o $(LIB) $(CFLAGS)
gcc mongoose.c main.c -pthread -lnsl -lsocket -o $(PROG) $(CFLAGS)
$(CC) mongoose.c main.c -pthread -lnsl -lsocket -o $(PROG) $(CFLAGS)
##########################################################################
@@ -55,18 +56,19 @@ solaris:
##########################################################################
# Using Visual Studio 6.0. To build Mongoose:
# o Set VC variable below to where VS 6.0 is installed on your system
# o Set MSVC variable below to where VS 6.0 is installed on your system
# o Run "PATH_TO_VC6\bin\nmake windows"
VC= z:
CYA= y:
#DBG= /Zi /DDEBUG /Od
DBG= /DNDEBUG /O1
CL= cl /MD /TC /nologo $(DBG) /Gz /W3 /DNO_SSL_DL
GUILIB= user32.lib shell32.lib
LINK= /link /incremental:no /libpath:$(VC)\lib /subsystem:windows \
ws2_32.lib advapi32.lib cyassl.lib
CYAFL = /c /I $(CYA)/include -I $(CYA)/include/openssl \
MSVC = e:/vc6
CYA = e:/cyassl-2.0.0rc2
#DBG = /Zi /DDEBUG /Od
DBG = /DNDEBUG /O1
CL = $(MSVC)/bin/cl /MD /TC /nologo $(DBG) /Gz /W3 /DNO_SSL_DL \
/I$(MSVC)/include
GUILIB= user32.lib shell32.lib
LINK = /link /incremental:no /libpath:$(MSVC)/lib /machine:IX86 \
/subsystem:windows ws2_32.lib advapi32.lib cyassl.lib
CYAFL = /c /I $(CYA)/include -I $(CYA)/include/openssl /I$(MSVC)/INCLUDE \
/I $(CYA)/ctaocrypt/include /D _LIB /D OPENSSL_EXTRA
CYASRC= \
@@ -101,26 +103,26 @@ CYASRC= \
$(CYA)/ctaocrypt/src/sha512.c \
$(CYA)/ctaocrypt/src/tfm.c
cyassl:
cyassl.lib:
$(CL) $(CYASRC) $(CYAFL) $(DEF)
lib *.obj /out:cyassl.lib
$(MSVC)/bin/lib *.obj /out:$@
windows:
rc win32\res.rc
$(CL) main.c mongoose.c /GA $(LINK) win32\res.res \
windows: cyassl.lib
$(MSVC)/bin/rc win32\res.rc
$(CL) /I win32 main.c mongoose.c /GA $(LINK) win32\res.res \
$(GUILIB) /out:$(PROG).exe
$(CL) mongoose.c /GD $(LINK) /DLL /DEF:win32\dll.def /out:_$(PROG).dll
$(CL) mongoose.c /GD $(LINK) /DLL /DEF:win32\dll.def /out:$(PROG).dll
# Build for Windows under MinGW
#MINGWDBG= -DDEBUG -O0
#MINGWDBG= -DDEBUG -O0 -ggdb
MINGWDBG= -DNDEBUG -Os
#MINGWOPT= -W -Wall -mthreads -Wl,--subsystem,console $(MINGWDBG) -DHAVE_STDINT
MINGWOPT= -W -Wall -mthreads -Wl,--subsystem,windows $(MINGWDBG)
MINGWOPT= -W -Wall -mthreads -Wl,--subsystem,console $(MINGWDBG) -DHAVE_STDINT $(GCC_WARNINGS) $(COPT)
#MINGWOPT= -W -Wall -mthreads -Wl,--subsystem,windows $(MINGWDBG) -DHAVE_STDINT $(GCC_WARNINGS) $(COPT)
mingw:
windres win32\res.rc win32\res.o
gcc $(MINGWOPT) mongoose.c -lws2_32 \
-shared -Wl,--out-implib=$(PROG).lib -o _$(PROG).dll
gcc $(MINGWOPT) mongoose.c main.c win32\res.o -lws2_32 -ladvapi32 \
$(CC) $(MINGWOPT) mongoose.c -lws2_32 \
-shared -Wl,--out-implib=$(PROG).lib -o $(PROG).dll
$(CC) $(MINGWOPT) -Iwin32 mongoose.c main.c win32\res.o -lws2_32 -ladvapi32 \
-o $(PROG).exe
@@ -135,12 +137,11 @@ man:
# "TEST=unit make test" - perform unit test only
# "TEST=embedded" - test embedded API by building and testing test/embed.c
# "TEST=basic_tests" - perform basic tests only (no CGI, SSI..)
test: do_test
do_test:
tests:
perl test/test.pl $(TEST)
release: clean
F=mongoose-`perl -lne '/define\s+MONGOOSE_VERSION\s+"(\S+)"/ and print $$1' mongoose.c`.tgz ; cd .. && tar -czf x mongoose/{LICENSE,Makefile,bindings,examples,test,win32,mongoose.c,mongoose.h,mongoose.1,main.c} && mv x mongoose/$$F
clean:
rm -rf *.o *.core $(PROG) *.obj *.so $(PROG).txt *.dSYM *.tgz
rm -rf *.o *.core $(PROG) *.obj *.so $(PROG).txt *.dSYM *.tgz $(PROG).exe *.dll *.lib
+31
View File
@@ -0,0 +1,31 @@
Overview
--------
Mongoose is easy to use web server. It also can be used as embedded web server library to provide web interface to applications.
Mongoose executable does not depend on any external library or configuration. If it is copied to any directory and launched from there, it starts to serve that directory on port 8080 (so to access files, go to http://localhost:8080). If some additional config is required - for example, different listening port or IP-based access control, then a mongoose.conf file with respective options can be created in the same directory where executable lives. This makes Mongoose perfect for all sorts of demos, quick tests, file sharing, and Web programming.
Features
--------
- Crossplatform - works on Windows, MacOS and most flavors of UNIX
- CGI, SSL, SSI, Digest (MD5) authorization, Websocket, WEbDAV support
- Resumed download, URL rewrite support
- IP-based ACL, Windows service, GET, POST, HEAD, PUT, DELETE methods
- Small footprint: executable size is 40 kB on Linux 2.6 i386 system
- Embeddable with simple and clean API ([mongoose.h](https://github.com/valenok/mongoose/blob/master/mongoose.h)). The source is in single [mongoose.c](https://github.com/valenok/mongoose/blob/master/mongoose.c) file to make things easy.
- Embedding examples: [hello.c](https://github.com/valenok/mongoose/blob/master/examples/hello.c), [post.c](https://github.com/valenok/mongoose/blob/master/examples/post.c), [upload.c](https://github.com/valenok/mongoose/blob/master/examples/upload.c), [websocket.c](https://github.com/valenok/mongoose/blob/master/examples/websocket.c)
- Python and C# bindings
Mailing list
------------
You can read it online, subscribe to, or send a message at [mongoose-users](http://groups.google.com/group/mongoose-users).
Keep Sergey happy
-----------------
I have a [books wishlist](http://amzn.com/w/1OC2ZCPTQYIEP?sort=priority) on Amazon. If you feel brave, you can buy me a book!
+1 -1
View File
@@ -13,7 +13,7 @@ def EventHandler(event, conn):
if event == mongoose.HTTP_ERROR:
conn.printf('%s', 'HTTP/1.0 200 OK\r\n')
conn.printf('%s', 'Content-Type: text/plain\r\n\r\n')
conn.printf('HTTP error: %d\n', info.status_code)
conn.printf('HTTP error: %d\n', conn.reply_status_code)
return True
elif event == mongoose.NEW_REQUEST and info.uri == '/show':
conn.printf('%s', 'HTTP/1.0 200 OK\r\n')
+19 -9
View File
@@ -40,10 +40,15 @@ import ctypes
import os
NEW_REQUEST = 0
HTTP_ERROR = 1
EVENT_LOG = 2
INIT_SSL = 3
NEW_REQUEST = 0
REQUEST_COMPLETE = 1
HTTP_ERROR = 2
EVENT_LOG = 3
INIT_SSL = 4
WEBSOCKET_CONNECT = 5
WEBSOCKET_READY = 6
WEBSOCKET_MESSAGE = 7
WEBSOCKET_CLOSE = 8
class mg_header(ctypes.Structure):
@@ -57,16 +62,13 @@ class mg_header(ctypes.Structure):
class mg_request_info(ctypes.Structure):
"""A wrapper for struct mg_request_info."""
_fields_ = [
('user_data', ctypes.c_char_p),
('request_method', ctypes.c_char_p),
('uri', ctypes.c_char_p),
('http_version', ctypes.c_char_p),
('query_string', ctypes.c_char_p),
('remote_user', ctypes.c_char_p),
('log_message', ctypes.c_char_p),
('remote_ip', ctypes.c_long),
('remote_port', ctypes.c_int),
('status_code', ctypes.c_int),
('is_ssl', ctypes.c_int),
('num_headers', ctypes.c_int),
('http_headers', mg_header * 64),
@@ -84,6 +86,10 @@ class Connection(object):
self.m = mongoose
self.conn = ctypes.c_void_p(connection)
self.info = self.m.dll.mg_get_request_info(self.conn).contents
self.user_data = self.m.dll.mg_get_user_data(self.conn)
self.log_message = self.m.dll.mg_get_log_message(self.conn)
self.reply_status_code = self.m.dll.mg_get_reply_status_code(self.conn)
self.ssl_context = self.m.dll.mg_get_ssl_context(self.conn)
def get_header(self, name):
val = self.m.dll.mg_get_header(self.conn, name)
@@ -117,9 +123,9 @@ class Mongoose(object):
def __init__(self, callback, **kwargs):
if os.name == 'nt':
self.dll = ctypes.WinDLL('_mongoose.dll')
self.dll = ctypes.WinDLL('mongoose.dll')
else:
self.dll = ctypes.CDLL('_mongoose.so')
self.dll = ctypes.CDLL('libmongoose.so')
self.dll.mg_start.restype = ctypes.c_void_p
self.dll.mg_modify_passwords_file.restype = ctypes.c_int
@@ -131,6 +137,10 @@ class Mongoose(object):
self.dll.mg_get_cookie.restype = ctypes.c_int
self.dll.mg_get_option.restype = ctypes.c_char_p
self.dll.mg_get_request_info.restype = ctypes.POINTER(mg_request_info)
self.dll.mg_get_user_data.restype = ctypes.c_void_p
self.dll.mg_get_reply_status_code.restype = ctypes.c_int
self.dll.mg_get_log_message.restype = ctypes.c_char_p
self.dll.mg_get_ssl_context.restype = ctypes.c_void_p
if callback:
# Create a closure that will be called by the shared library.
+3
View File
@@ -4,4 +4,7 @@ all:
OS=`uname`; \
test "$$OS" = Linux && LIBS="-ldl" ; \
$(CC) $(CFLAGS) hello.c ../mongoose.c $$LIBS $(ADD) -o hello;
$(CC) $(CFLAGS) upload.c ../mongoose.c $$LIBS $(ADD) -o upload;
$(CC) $(CFLAGS) post.c ../mongoose.c $$LIBS $(ADD) -o post;
$(CC) $(CFLAGS) -DUSE_WEBSOCKET websocket.c ../mongoose.c $$LIBS $(ADD) -o websocket;
$(CC) $(CFLAGS) chat.c ../mongoose.c $$LIBS $(ADD) -o chat
+5 -3
View File
@@ -122,7 +122,7 @@ static int handle_jsonp(struct mg_connection *conn,
if (cb[0] != '\0') {
mg_printf(conn, "%s(", cb);
}
return cb[0] == '\0' ? 0 : 1;
}
@@ -369,8 +369,10 @@ int main(void) {
srand((unsigned) time(0));
// Setup and start Mongoose
ctx = mg_start(&event_handler, NULL, options);
assert(ctx != NULL);
if ((ctx = mg_start(&event_handler, NULL, options)) == NULL) {
printf("%s\n", "Cannot start chat server, fatal exit");
exit(EXIT_FAILURE);
}
// Wait until enter is pressed, then exit
printf("Chat server started on ports %s, press enter to quit.\n",
+11 -4
View File
@@ -16,6 +16,11 @@ chat.normalizeText = function(text) {
};
chat.refresh = function(data) {
if (data === undefined) {
return;
}
$.each(data, function(index, entry) {
var row = $('<div>').addClass('message-row').appendTo('#mml');
var timestamp = (new Date(entry.timestamp * 1000)).toLocaleTimeString();
@@ -42,7 +47,7 @@ chat.refresh = function(data) {
}
};
chat.getMessages = function() {
chat.getMessages = function(enter_loop) {
$.ajax({
dataType: 'jsonp',
url: chat.backendUrl + '/ajax/get_messages',
@@ -51,7 +56,9 @@ chat.getMessages = function() {
error: function() {
},
});
window.setTimeout(chat.getMessages, chat.getMessagesIntervalMs);
if (enter_loop) {
window.setTimeout('chat.getMessages(true)', chat.getMessagesIntervalMs);
}
};
chat.handleMenuItemClick = function(ev) {
@@ -81,7 +88,7 @@ chat.handleMessageInput = function(ev) {
success: function(ev) {
input.value = '';
input.disabled = false;
chat.getMessages();
chat.getMessages(false);
},
error: function(ev) {
chat.showError('Error sending message');
@@ -93,7 +100,7 @@ chat.handleMessageInput = function(ev) {
$(document).ready(function() {
$('.menu-item').click(chat.handleMenuItemClick);
$('.message-input').keypress(chat.handleMessageInput);
chat.getMessages();
chat.getMessages(true);
});
// vim:ts=2:sw=2:et
+61
View File
@@ -0,0 +1,61 @@
#include <stdio.h>
#include <string.h>
#include "mongoose.h"
static const char *html_form =
"<html><body>POST example."
"<form method=\"POST\" action=\"/handle_post_request\">"
"Input 1: <input type=\"text\" name=\"input_1\" /> <br/>"
"Input 2: <input type=\"text\" name=\"input_2\" /> <br/>"
"<input type=\"submit\" />"
"</form></body></html>";
static void *callback(enum mg_event event,
struct mg_connection *conn) {
const struct mg_request_info *ri = mg_get_request_info(conn);
if (event == MG_NEW_REQUEST) {
if (!strcmp(ri->uri, "/handle_post_request")) {
// User has submitted a form, show submitted data and a variable value
char post_data[1024],
input1[sizeof(post_data)], input2[sizeof(post_data)];
int post_data_len;
// Read POST data
post_data_len = mg_read(conn, post_data, sizeof(post_data));
// Parse form data. input1 and input2 are guaranteed to be NUL-terminated
mg_get_var(post_data, post_data_len, "input_1", input1, sizeof(input1));
mg_get_var(post_data, post_data_len, "input_2", input2, sizeof(input2));
mg_printf(conn, "HTTP/1.0 200 OK\r\n"
"Content-Type: text/plain\r\n\r\n"
"Submitted data: [%.*s]\n"
"Submitted data length: %d bytes\n"
"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 {
return NULL;
}
}
int main(void) {
struct mg_context *ctx;
const char *options[] = {"listening_ports", "8080", NULL};
ctx = mg_start(&callback, NULL, options);
getchar(); // Wait until user hits "enter"
mg_stop(ctx);
return 0;
}
+130
View File
@@ -0,0 +1,130 @@
// Copyright (c) 2004-2012 Sergey Lyubka
// This file is a part of mongoose project, http://github.com/valenok/mongoose
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <inttypes.h>
#include <unistd.h>
#include "mongoose.h"
// Make sure that form has enctype="multipart/form-data" attribute
static const char *html_form =
"<html><body>Upload example."
"<form method=\"POST\" action=\"/handle_post_request\" "
" enctype=\"multipart/form-data\">"
"<input type=\"file\" name=\"file\" /> <br/>"
"<input type=\"submit\" value=\"Upload\" />"
"</form></body></html>";
static const char *HTTP_500 = "HTTP/1.0 500 Server Error\r\n\r\n";
static void handle_file_upload(struct mg_connection *conn) {
const char *cl_header;
char post_data[16 * 1024], path[999], file_name[1024], mime_type[100],
buf[BUFSIZ], *eop, *s, *p;
FILE *fp;
long long int cl, written;
int fd, n, post_data_len;
// Figure out total content length. Return if it is not present or invalid.
cl_header = mg_get_header(conn, "Content-Length");
if (cl_header == NULL || (cl = strtoll(cl_header, NULL, 10)) <= 0) {
mg_printf(conn, "%s%s", HTTP_500, "Invalid Conent-Length");
return;
}
// Read the initial chunk into memory. This should be multipart POST data.
// Parse headers, where we should find file name and content-type.
post_data_len = mg_read(conn, post_data, sizeof(post_data));
file_name[0] = mime_type[0] = '\0';
for (s = p = post_data; p < &post_data[post_data_len]; p++) {
if (p[0] == '\r' && p[1] == '\n') {
if (s == p) {
p += 2;
break; // End of headers
}
p[0] = p[1] = '\0';
sscanf(s, "Content-Type: %99s", mime_type);
// TODO(lsm): don't expect filename to be the 3rd field,
// parse the header properly instead.
sscanf(s, "Content-Disposition: %*s %*s filename=\"%1023[^\"]",
file_name);
s = p + 2;
}
}
// Finished parsing headers. Now "p" points to the first byte of data.
// Calculate file size
cl -= p - post_data; // Subtract headers size
cl -= strlen(post_data); // Subtract the boundary marker at the end
cl -= 6; // Subtract "\r\n" before and after boundary
// Construct destination file name. Write to /tmp, do not allow
// paths that contain slashes.
if ((s = strrchr(file_name, '/')) == NULL) {
s = file_name;
}
snprintf(path, sizeof(path), "/tmp/%s", s);
if (file_name[0] == '\0') {
mg_printf(conn, "%s%s", HTTP_500, "Can't get file name");
} else if (cl <= 0) {
mg_printf(conn, "%s%s", HTTP_500, "Empty file");
} else if ((fd = open(path, O_CREAT | O_TRUNC |
O_WRONLY | O_EXLOCK | O_CLOEXEC)) < 0) {
// We're opening the file with exclusive lock held. This guarantee us that
// there is no other thread can save into the same file simultaneously.
mg_printf(conn, "%s%s", HTTP_500, "Cannot open file");
} else if ((fp = fdopen(fd, "w")) == NULL) {
mg_printf(conn, "%s%s", HTTP_500, "Cannot reopen file stream");
close(fd);
} else {
// Success. Write data into the file.
eop = post_data + post_data_len;
n = p + cl > eop ? (int) (eop - p) : (int) cl;
(void) fwrite(p, 1, n, fp);
written = n;
while (written < cl &&
(n = mg_read(conn, buf, cl - written > (long long) sizeof(buf) ?
sizeof(buf) : cl - written)) > 0) {
(void) fwrite(buf, 1, n, fp);
written += n;
}
(void) fclose(fp);
mg_printf(conn, "HTTP/1.0 200 OK\r\n\r\n"
"Saved to [%s], written %llu bytes", path, cl);
}
}
static void *callback(enum mg_event event, struct mg_connection *conn) {
const struct mg_request_info *ri = mg_get_request_info(conn);
if (event == MG_NEW_REQUEST) {
if (!strcmp(ri->uri, "/handle_post_request")) {
handle_file_upload(conn);
} 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 {
return NULL;
}
}
int main(void) {
struct mg_context *ctx;
const char *options[] = {"listening_ports", "8080", NULL};
ctx = mg_start(&callback, NULL, options);
getchar(); // Wait until user hits "enter"
mg_stop(ctx);
return 0;
}
+75
View File
@@ -0,0 +1,75 @@
// Copyright (c) 2004-2012 Sergey Lyubka
// This file is a part of mongoose project, http://github.com/valenok/mongoose
#include <stdio.h>
#include <string.h>
#include "mongoose.h"
static void *callback(enum mg_event event, struct mg_connection *conn) {
if (event == MG_WEBSOCKET_READY) {
unsigned char buf[40];
buf[0] = 0x81;
buf[1] = snprintf((char *) buf + 2, sizeof(buf) - 2, "%s", "server ready");
mg_write(conn, buf, 2 + buf[1]);
return ""; // MG_WEBSOCKET_READY return value is ignored
} else if (event == MG_WEBSOCKET_MESSAGE) {
unsigned char buf[200], reply[200];
int n, i, mask_len, xor, msg_len, len;
// Read message from the client.
// Accept only small (<126 bytes) messages.
len = 0;
msg_len = mask_len = 0;
for (;;) {
if ((n = mg_read(conn, buf + len, sizeof(buf) - len)) <= 0) {
return ""; // 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 ""; // 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
reply[0] = 0x81; // text, FIN set
reply[1] = msg_len;
// Copy message from request to reply, applying the mask if required.
for (i = 0; i < msg_len; i++) {
xor = mask_len == 0 ? 0 : buf[2 + (i % 4)];
reply[i + 2] = buf[i + 2 + mask_len] ^ xor;
}
// Echo the message back to the client
mg_write(conn, reply, 2 + msg_len);
// Return non-NULL means stoping websocket conversation.
// Close the conversation if client has sent us "exit" string.
return memcmp(reply + 2, "exit", 4) == 0 ? "" : NULL;
} else {
return NULL;
}
}
int main(void) {
struct mg_context *ctx;
const char *options[] = {
"listening_ports", "8080",
"document_root", "websocket_html_root",
NULL
};
ctx = mg_start(&callback, NULL, options);
getchar(); // Wait until user hits "enter"
mg_stop(ctx);
return 0;
}
+44
View File
@@ -0,0 +1,44 @@
<!DOCTYPE html>
<meta charset="utf-8" />
<title>WebSocket Test</title>
<script language="javascript" type="text/javascript">
var writeToScreen = function(message) {
var div = document.createElement('div');
div.innerHTML = message;
document.getElementById('output').appendChild(div);
};
window.onload = function() {
var url = 'ws://' + window.location.host + '/foo';
websocket = new WebSocket(url);
websocket.onopen = function(ev) {
writeToScreen('CONNECTED');
var message = 'Не всё подчиняется разуму. Но всё подчиняется упорству. ';
writeToScreen('SENT: ' + message);
websocket.send(message);
};
websocket.onclose = function(ev) {
writeToScreen('DISCONNECTED');
};
websocket.onmessage = function(ev) {
writeToScreen('<span style="color: blue;">RESPONSE: ' + ev.data +
' </span>');
websocket.send('exit');
};
websocket.onerror = function(ev) {
writeToScreen('<span style="color: red; ">ERROR: </span> ' + ev.data);
};
};
</script>
<style> div {font: small Verdana; } </style>
<h2>Mongoose WebSocket Test</h2>
<div style="width: 400px; color: #aaa; padding: 1em; ">
This page code creates websocket to the URI "/foo",
sends a message to it, waits for the reply, then sends an "exit" message.
Server must echo all messages back, and terminate the conversation after
receiving the "exit" message.
</div>
<div id="output"></div>
</html>
+8 -3
View File
@@ -33,6 +33,7 @@
#include <limits.h>
#include <stddef.h>
#include <stdarg.h>
#include <ctype.h>
#include "mongoose.h"
@@ -191,7 +192,8 @@ static void process_command_line_arguments(char *argv[], char **options) {
line_no++;
// Ignore empty lines and comments
if (line[0] == '#' || line[0] == '\n')
for (i = 0; isspace(* (unsigned char *) &line[i]); ) i++;
if (line[i] == '#' || line[i] == '\0')
continue;
if (sscanf(line, "%s %[^\r\n#]", opt, val) != 2) {
@@ -203,7 +205,7 @@ static void process_command_line_arguments(char *argv[], char **options) {
(void) fclose(fp);
}
// Now handle command line flags. They override config file settings.
// Handle command line flags. They override config file and default settings.
for (i = cmd_line_opts_start; argv[i] != NULL; i += 2) {
if (argv[i][0] != '-' || argv[i + 1] == NULL) {
show_usage_and_exit();
@@ -219,9 +221,11 @@ static void init_server_name(void) {
static void *mongoose_callback(enum mg_event ev, struct mg_connection *conn) {
if (ev == MG_EVENT_LOG) {
printf("%s\n", mg_get_request_info(conn)->log_message);
printf("%s\n", mg_get_log_message(conn));
}
// Returning NULL marks request as not handled, signalling mongoose to
// proceed with handling it.
return NULL;
}
@@ -483,6 +487,7 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR cmdline, int show) {
DispatchMessage(&msg);
}
// Return the WM_QUIT value.
return msg.wParam;
}
#else
+13 -3
View File
@@ -1,7 +1,7 @@
.\" Process this file with
.\" groff -man -Tascii mongoose.1
.\" $Id: mongoose.1,v 1.12 2008/11/29 15:32:42 drozd Exp $
.Dd Aug 31, 2010
.Dd Sep 23, 2012
.Dt mongoose 1
.Sh NAME
.Nm mongoose
@@ -82,8 +82,6 @@ Use
as a CGI interpreter for all CGI scripts regardless script extension.
Mongoose decides which interpreter to use by looking at
the first line of a CGI script. Default: "".
.It Fl M Ar max_request_size
Maximum HTTP request size in bytes. Default: "16384"
.It Fl P Ar protect_uri
Comma separated list of URI=PATH pairs, specifying that given URIs
must be protected with respected password files. Default: ""
@@ -93,6 +91,18 @@ Authorization realm. Default: "mydomain.com"
All files that fully match ssi_pattern are treated as SSI.
Unknown SSI directives are silently ignored. Currently, two SSI directives
are supported, "include" and "exec". Default: "**.shtml$|**.shtm$"
.It Fl T Ar throttle
Limit download speed for clients.
.Ar throttle
is a comma-separated list of key=value pairs, where
key could be a '*' character (limit for all connections), a subnet in form
x.x.x.x/mask (limit for a given subnet, for example 10.0.0.0/8), or an
URI prefix pattern (limit for the set of URIs, for example /foo/**). The value
is a floating-point number of bytes per second, optionally followed by a
`k' or `m' character, meaning kilobytes and megabytes respectively. A limit
of 0 means unlimited rate. The last matching rule wins. For example,
"*=1k,10.0.0.0/8" means limit everybody to 1 kilobyte per second, but give
people from 10/8 subnet unlimited speed. Default: ""
.It Fl a Ar access_log_file
Access log file. Default: "", no logging is done.
.It Fl d Ar enable_directory_listing
+754 -344
View File
File diff suppressed because it is too large. Load diff
+58 -30
View File
@@ -1,4 +1,4 @@
// Copyright (c) 2004-2011 Sergey Lyubka
// Copyright (c) 2004-2012 Sergey Lyubka
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -34,16 +34,13 @@ struct mg_connection; // Handle for the individual connection
// This structure contains information about the HTTP request.
struct mg_request_info {
void *user_data; // User-defined pointer passed to mg_start()
char *request_method; // "GET", "POST", etc
char *uri; // URL-decoded URI
char *http_version; // E.g. "1.0", "1.1"
char *query_string; // URL part after '?' (not including '?') or NULL
char *remote_user; // Authenticated user, or NULL if no auth used
char *log_message; // Mongoose error log message, MG_EVENT_LOG only
long remote_ip; // Client's IP address
int remote_port; // Client's port
int status_code; // HTTP reply status code, e.g. 200
int is_ssl; // 1 if SSL-ed, 0 if not
int num_headers; // Number of headers
struct mg_header {
@@ -52,16 +49,23 @@ struct mg_request_info {
} http_headers[64]; // Maximum 64 headers
};
// Various events on which user-defined function is called by Mongoose.
enum mg_event {
MG_NEW_REQUEST, // New HTTP request has arrived from the client
MG_HTTP_ERROR, // HTTP error must be returned to the client
MG_EVENT_LOG, // Mongoose logs an event, request_info.log_message
MG_INIT_SSL, // Mongoose initializes SSL. Instead of mg_connection *,
// SSL context is passed to the callback function.
MG_REQUEST_COMPLETE // Mongoose has finished handling the request
MG_NEW_REQUEST, // New HTTP request has arrived from the client
MG_REQUEST_COMPLETE, // Mongoose has finished handling the request
MG_HTTP_ERROR, // HTTP error must be returned to the client
MG_EVENT_LOG, // Mongoose logs an event, request_info.log_message
MG_INIT_SSL, // SSL initialization, sent before certificate setup
MG_WEBSOCKET_CONNECT, // Sent on HTTP connect, before websocket handshake.
// If user callback returns NULL, then mongoose proceeds
// with handshake, otherwise it closes the connection.
MG_WEBSOCKET_READY, // Handshake has been successfully completed.
MG_WEBSOCKET_MESSAGE, // Incoming message from the client
MG_WEBSOCKET_CLOSE, // Client has closed the connection
};
// Prototype for the user-defined function. Mongoose calls this function
// on every MG_* event.
//
@@ -77,8 +81,7 @@ enum mg_event {
// 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);
typedef void *(*mg_callback_t)(enum mg_event event, struct mg_connection *conn);
// Start web server.
@@ -151,26 +154,49 @@ int mg_modify_passwords_file(const char *passwords_file_name,
const char *password);
// Return mg_request_info structure associated with the request.
// Always succeeds.
const struct mg_request_info *mg_get_request_info(struct mg_connection *);
// Return information associated with the request.
// These functions always succeed.
const struct mg_request_info *mg_get_request_info(const struct mg_connection *);
void *mg_get_user_data(struct mg_connection *);
const char *mg_get_log_message(const struct mg_connection *);
int mg_get_reply_status_code(const struct mg_connection *);
void *mg_get_ssl_context(const struct mg_connection *);
// Send data to the client.
// Return:
// 0 when the connection has been closed
// -1 on error
// number of bytes written on success
int mg_write(struct mg_connection *, const void *buf, size_t len);
// Send data to the browser using printf() semantics.
//
// Works exactly like mg_write(), but allows to do message formatting.
// Note that mg_printf() uses internal buffer of size IO_BUF_SIZE
// (8 Kb by default) as temporary message storage for formatting. Do not
// print data that is bigger than that, otherwise it will be truncated.
int mg_printf(struct mg_connection *, const char *fmt, ...)
#ifdef __GNUC__
__attribute__((format(printf, 2, 3)))
// Below are the macros for enabling compiler-specific checks for
// printf-like arguments.
#undef PRINTF_FORMAT_STRING
#if _MSC_VER >= 1400
#include <sal.h>
#if _MSC_VER > 1400
#define PRINTF_FORMAT_STRING(s) _Printf_format_string_ s
#else
#define PRINTF_FORMAT_STRING(s) __format_string s
#endif
;
#else
#define PRINTF_FORMAT_STRING(s) s
#endif
#ifdef __GNUC__
#define PRINTF_ARGS(x, y) __attribute__((format(printf, x, y)))
#else
#define PRINTF_ARGS(x, y)
#endif
int mg_printf(struct mg_connection *,
PRINTF_FORMAT_STRING(const char *fmt), ...) PRINTF_ARGS(2, 3);
// Send contents of the entire file together with HTTP headers.
@@ -201,10 +227,12 @@ const char *mg_get_header(const struct mg_connection *, const char *name);
//
// Return:
// On success, length of the decoded variable.
// On error, -1 (variable not found, or destination buffer is too small).
// On error:
// -1 (variable not found, or destination buffer is too small).
// -2 (destination buffer is NULL or zero length).
//
// Destination buffer is guaranteed to be '\0' - terminated. In case of
// failure, dst[0] == '\0'.
// Destination buffer is guaranteed to be '\0' - terminated if it is not
// NULL or zero length. In case of failure, dst[0] == '\0'.
int mg_get_var(const char *data, size_t data_len,
const char *var_name, char *buf, size_t buf_len);
@@ -216,7 +244,7 @@ int mg_get_var(const char *data, size_t data_len,
//
// Return:
// On success, value length.
// On error, 0 (either "Cookie:" header is not present at all, or the
// On error, -1 (either "Cookie:" header is not present at all, or the
// requested parameter is not found, or destination buffer is too small
// to hold the value).
int mg_get_cookie(const struct mg_connection *,
@@ -243,8 +271,8 @@ void mg_close_connection(struct mg_connection *conn);
// Return:
// On error, NULL
// On success, opened file stream to the downloaded contents. The stream
// is positioned to the end of the file. It is a user responsibility
// to fclose() opened file stream.
// is positioned to the end of the file. It is the user's responsibility
// to fclose() the opened file stream.
FILE *mg_fetch(struct mg_context *ctx, const char *url, const char *path,
char *buf, size_t buf_len, struct mg_request_info *request_info);
@@ -266,11 +294,11 @@ const char *mg_version(void);
// MD5 hash given strings.
// Buffer 'buf' must be 33 bytes long. Varargs is a NULL terminated list of
// asciiz strings. When function returns, buf will contain human-readable
// ASCIIz strings. When function returns, buf will contain human-readable
// MD5 hash. Example:
// char buf[33];
// mg_md5(buf, "aa", "bb", NULL);
void mg_md5(char *buf, ...);
void mg_md5(char buf[33], ...);
#ifdef __cplusplus
-1
View File
@@ -1 +0,0 @@
blah
+3 -2
View File
@@ -119,9 +119,10 @@ static void test_get_request_info(struct mg_connection *conn,
static void test_error(struct mg_connection *conn,
const struct mg_request_info *ri) {
(void) ri;
mg_printf(conn, "HTTP/1.1 %d XX\r\n"
"Conntection: close\r\n\r\n", ri->status_code);
mg_printf(conn, "Error: [%d]", ri->status_code);
"Conntection: close\r\n\r\n", mg_get_reply_status_code(conn));
mg_printf(conn, "Error: [%d]", mg_get_reply_status_code(conn));
}
static void test_post(struct mg_connection *conn,
-2
View File
@@ -215,8 +215,6 @@ $num_requests++;
write_file("$root/a+.txt", '');
o("GET /a+.txt HTTP/1.0\n\n", 'HTTP/1.1 200 OK', 'URL-decoding, + in URI');
o("GET /%5c/a.txt HTTP/1.0\n\n", 'blah', 'GET dir backslash');
# Test HTTP version parsing
o("GET / HTTPX/1.0\r\n\r\n", '400 Bad Request', 'Bad HTTP Version', 0);
o("GET / HTTP/x.1\r\n\r\n", '505 HTTP', 'Bad HTTP maj Version');
+71 -8
View File
@@ -1,3 +1,4 @@
#define USE_WEBSOCKET
#include "mongoose.c"
#define FATAL(str, line) do { \
@@ -64,10 +65,10 @@ static void test_should_keep_alive(void) {
parse_http_request(req4, sizeof(req4), &conn.request_info);
ASSERT(should_keep_alive(&conn) == 1);
conn.request_info.status_code = 401;
conn.status_code = 401;
ASSERT(should_keep_alive(&conn) == 0);
conn.request_info.status_code = 200;
conn.status_code = 200;
conn.must_close = 1;
ASSERT(should_keep_alive(&conn) == 0);
}
@@ -111,17 +112,14 @@ static void test_remove_double_dots() {
{"/...///", "/./"},
{"/a...///", "/a.../"},
{"/.x", "/.x"},
#if defined(_WIN32)
{"/\\", "/"},
#else
{"/\\", "/\\"},
#endif
{"/a\\", "/a\\"},
{"/a\\\\...", "/a\\."},
};
size_t i;
for (i = 0; i < ARRAY_SIZE(data); i++) {
//printf("[%s] -> [%s]\n", data[i].before, data[i].after);
printf("[%s] -> [%s]\n", data[i].before, data[i].after);
remove_double_dots_and_double_slashes(data[i].before);
ASSERT(strcmp(data[i].before, data[i].after) == 0);
}
@@ -138,7 +136,7 @@ static void *event_handler(enum mg_event event,
"%s", (int) strlen(fetch_data), fetch_data);
return "";
} else if (event == MG_EVENT_LOG) {
printf("%s\n", request_info->log_message);
printf("%s\n", mg_get_log_message(conn));
}
return NULL;
@@ -196,11 +194,76 @@ static void test_mg_fetch(void) {
mg_stop(ctx);
}
static void test_base64_encode(void) {
const char *in[] = {"a", "ab", "abc", "abcd", NULL};
const char *out[] = {"YQ==", "YWI=", "YWJj", "YWJjZA=="};
char buf[100];
int i;
for (i = 0; in[i] != NULL; i++) {
base64_encode((unsigned char *) in[i], strlen(in[i]), buf);
printf("[%s] [%s]\n", out[i], buf);
ASSERT(!strcmp(buf, out[i]));
}
}
static void test_mg_get_var(void) {
static const char *post[] = {"a=1&&b=2&d&=&c=3%20&e=", NULL};
char buf[20];
ASSERT(mg_get_var(post[0], strlen(post[0]), "a", buf, sizeof(buf)) == 1);
ASSERT(buf[0] == '1' && buf[1] == '\0');
ASSERT(mg_get_var(post[0], strlen(post[0]), "b", buf, sizeof(buf)) == 1);
ASSERT(buf[0] == '2' && buf[1] == '\0');
ASSERT(mg_get_var(post[0], strlen(post[0]), "c", buf, sizeof(buf)) == 2);
ASSERT(buf[0] == '3' && buf[1] == ' ' && buf[2] == '\0');
ASSERT(mg_get_var(post[0], strlen(post[0]), "e", buf, sizeof(buf)) == 0);
ASSERT(buf[0] == '\0');
ASSERT(mg_get_var(post[0], strlen(post[0]), "d", buf, sizeof(buf)) == -1);
ASSERT(mg_get_var(post[0], strlen(post[0]), "c", buf, 2) == -1);
ASSERT(mg_get_var(post[0], strlen(post[0]), "x", NULL, 10) == -2);
ASSERT(mg_get_var(post[0], strlen(post[0]), "x", buf, 0) == -2);
}
static void test_set_throttle(void) {
ASSERT(set_throttle(NULL, 0x0a000001, "/") == 0);
ASSERT(set_throttle("10.0.0.0/8=20", 0x0a000001, "/") == 20);
ASSERT(set_throttle("10.0.0.0/8=0.5k", 0x0a000001, "/") == 512);
ASSERT(set_throttle("10.0.0.0/8=17m", 0x0a000001, "/") == 1048576 * 17);
ASSERT(set_throttle("10.0.0.0/8=1x", 0x0a000001, "/") == 0);
ASSERT(set_throttle("10.0.0.0/8=5,0.0.0.0/0=10", 0x0a000001, "/") == 10);
ASSERT(set_throttle("10.0.0.0/8=5,/foo/**=7", 0x0a000001, "/index") == 5);
ASSERT(set_throttle("10.0.0.0/8=5,/foo/**=7", 0x0a000001, "/foo/x") == 7);
ASSERT(set_throttle("10.0.0.0/8=5,/foo/**=7", 0x0b000001, "/foxo/x") == 0);
ASSERT(set_throttle("10.0.0.0/8=5,*=1", 0x0b000001, "/foxo/x") == 1);
}
static void test_next_option(void) {
const char *p, *list = "x/8,/y**=1;2k,z";
struct vec a, b;
int i;
ASSERT(next_option(NULL, &a, &b) == NULL);
for (i = 0, p = list; (p = next_option(p, &a, &b)) != NULL; i++) {
ASSERT(i != 0 || (a.ptr == list && a.len == 3 && b.len == 0));
ASSERT(i != 1 || (a.ptr == list + 4 && a.len == 4 && b.ptr == list + 9 &&
b.len == 4));
ASSERT(i != 2 || (a.ptr == list + 14 && a.len == 1 && b.len == 0));
}
}
int main(void) {
test_base64_encode();
test_match_prefix();
test_remove_double_dots();
test_should_keep_alive();
test_parse_http_request();
test_mg_fetch();
test_mg_get_var();
test_set_throttle();
test_next_option();
return 0;
}
+9
View File
@@ -0,0 +1,9 @@
<html>
<form method="post">
<input name="x" type="text" />
<input type="submit" />
</form>
<? echo $_POST["x"]; ?>
</html>