├── LICENSE ├── README.md ├── build ├── Makefile._gcc ├── Makefile.linux ├── Makefile.mingw └── Makefile.msvc ├── duktape ├── duk_config.h ├── dukpylib.c ├── dukpylib.h ├── duktape.c ├── duktape.h ├── subprocess.h ├── subprocess_linux.c └── subprocess_w32.c ├── hashmap ├── hashmap.c ├── hashmap.h ├── hashmap.perf └── hashmap_perf.c ├── iconv.lib.7z ├── libhttpd ├── http_buffer.h ├── http_client.c ├── http_client.h ├── http_common.h ├── http_connection.h ├── http_content.c ├── http_content.h ├── http_map.c ├── http_map.h ├── http_mpm.c ├── http_mpm.h ├── http_parse.c ├── http_parse.h ├── http_sendrecv.c ├── http_sendrecv.h ├── http_server.c ├── http_server.h ├── http_string.c ├── http_string.h ├── http_sys.h ├── http_sys_linux.c ├── http_sys_w32.c ├── http_urldecode.c ├── http_urldecode.h ├── http_urlencode.c ├── http_urlencode.h ├── libhttp.c ├── libhttp.h ├── wsgi.txt ├── wsgi_server.c └── wsgi_server.h ├── libsocket ├── libsocket.h ├── usocket.c └── wsocket.c ├── manual ├── api.html ├── guide.html └── style.css ├── memo ├── test ├── duk_server.c ├── put.php ├── shell.c ├── shell2.c ├── simple_client.c ├── simple_server.c └── wsgi_app.js └── testjs ├── _file_be_included1.js ├── _file_be_included2.js ├── _file_be_included4.js ├── _mod_be_require.js ├── cp_stdin_to_stdout.c ├── test_array.js ├── test_dir_globals.js ├── test_error.js ├── test_function.js ├── test_include.js ├── test_include ├── _file_be_included.js ├── _file_be_included1.js ├── _file_be_included3.js └── _file_be_included4.js ├── test_json.js ├── test_os_path.js ├── test_regexp.js ├── test_require.js ├── test_split.js ├── test_subprocess.js ├── test_subprocess_cat.js ├── test_subprocess_commandline.js ├── test_subprocess_err.js ├── test_subprocess_runner.c ├── test_throw.js ├── test_time.js └── test_unicode.js /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 william wilberforce junior 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dukserver 2 | A simple HTTP-Server base on Duktape 3 | 4 | 5 | I want to build a remote mantain web server for ARM-based linux. 6 | First I choose Python, but cross-compile is painful, and Python is very huge size. 7 | 8 | So I decided to find some light script engine, such like lua. 9 | But I don't like LUA Syntax. 10 | 11 | Finally I found Duktape in my codes collection. And pick it up, try again. 12 | So I base on luasocket and duktape, I implement a light http server. 13 | 14 | But duktape is leak of buildin function. 15 | So I implement python like library. 16 | And extend String.encode(encoding) and String.decode(encodeing) base on libiconv. 17 | And override default Duktape.modSearch function. 18 | 19 | 20 | ```javascript 21 | var fs = require('fs'); 22 | var os = require('os'); 23 | var path = require('os.path'); 24 | var sys = require('sys'); 25 | var time = requre('time'); 26 | var _subprocess = require('_subprocess'); 27 | 28 | //file access 29 | var f = fs.open('../../file.bin'); 30 | var text = f.read(); 31 | f.close(); 32 | 33 | //reflaction method 34 | var m = dir(f); 35 | for (var k in m) { 36 | print(' ' + k + ': ' + m[k]); 37 | } 38 | 39 | print(" os.getcwd(): " + 40 | os.getcwd()); 41 | 42 | print(" os.path.split('C:'): " + 43 | os.path.split('C:')); 44 | print(" os.path.split('C:/'): " + 45 | os.path.split('C:/')); 46 | print(" os.path.split('/ewfwef/ffff.js'): " + 47 | os.path.split('/ewfwef/ffff.js')); 48 | 49 | print(" os.path.splitext('/ewfwef/ffffjs'): " + 50 | os.path.splitext('/ewfwef/ffffjs')); 51 | print(" os.path.splitext('c:\\ewfwef\\ffff.js'): " + 52 | os.path.splitext('c:\\ewfwef\\ffff.js')); 53 | print(" os.path.splitext('c:/ewfwef/ffff.js'): " + 54 | os.path.splitext('c:/ewfwef/ffff.js')); 55 | 56 | print(" os.path.normpath('test/../.././hello.js'): " + 57 | os.path.normpath('test/../.././hello.js')); 58 | 59 | print(" os.path.abspath('test/../.././hello.js'): " + 60 | os.path.abspath('test/../.././hello.js')); 61 | 62 | print(" os.path.join('C:/', 'test', 'file.js')" + 63 | os.path.join('C:/', 'test', 'file.js')); 64 | 65 | //string encode, decode 66 | var str_utf8 = 'hello world'; 67 | var str_ucs2 = str_utf8.decode('UTF-8'); 68 | var str_gbk = str_utf8.encode('GBK'); 69 | 70 | //subprocess 71 | var ps = _subprocess.psopen('ls', '-al'); 72 | while (1) { 73 | var out = ps.stdout.read(); 74 | if (out == null) { 75 | break; 76 | } 77 | print(out); 78 | } 79 | ps.wait(); 80 | ps.close(); 81 | ``` 82 | 83 | Duktape Server: 84 | * libhttpd/wsgi.txt: A example wsgi variable dump from mod_wsig+apache 85 | * libhttpd/wsgi_server.c: Embedded duktape to libhttpd, base on http_mpm 86 | * libhttpd/wsgi_server.h: Embedded duktape to libhttpd, base on http_mpm 87 | 88 | Build Script: 89 | * build/Makefile.msvc: Build script for Visual Studio 2010 90 | * build/Makefile.mingw: Build script for MSYS mingw32 91 | * build/Makefile.linux: Build script for Linux 92 | 93 | Duktape files [https://github.com/svaarala/duktape]: 94 | * duktape/duk_config.h 95 | * duktape/duktape.h 96 | * duktape/duktape.c 97 | 98 | Duktape python like library: 99 | * duktape/subprocess.h: A python like popen. 100 | * duktape/subprocess_win32.h: for Windows platform 101 | * duktape/subprocess_linux.h: for Linux platform 102 | * duktape/dukpylib.h: A python like library 103 | * duktape/dukpylib.c: A python like library 104 | 105 | LuaSocket [http://luaforge.net/projects/luasocket/]: 106 | * libsocket/libsocket.h 107 | * libsocket/usocket.c 108 | * libsocket/wsocket.c 109 | 110 | Http/Httpd Library: 111 | * libhttpd/http_buffer.h: A dynamic buffer interface 112 | * libhttpd/http_client.c: Http Client interface 113 | * libhttpd/http_client.h: Http Client interface 114 | * libhttpd/http_common.h: Common define for this library 115 | * libhttpd/http_connection.h: Connection data struct 116 | * libhttpd/http_content.c: Common request, response data struct 117 | * libhttpd/http_content.h: Common request, response data struct 118 | * libhttpd/http_map.c: Simple map 119 | * libhttpd/http_map.h: Simple map 120 | * libhttpd/http_mpm.c: Multi-Thread MPM wrap server interface 121 | * libhttpd/http_mpm.h: Multi-Thread MPM wrap server interface 122 | * libhttpd/http_parse.c: Parser of headers 123 | * libhttpd/http_parse.h: Parser of headers 124 | * libhttpd/http_sendrecv.c: Request and Response interface 125 | * libhttpd/http_sendrecv.h: Request and Response interface 126 | * libhttpd/http_server.c: Http Server interface 127 | * libhttpd/http_server.h: Http Server interface 128 | * libhttpd/http_string.c: Some string function 129 | * libhttpd/http_string.h: Some string function 130 | * libhttpd/http_sys.h: Abs layer of platform 131 | * libhttpd/http_sys_linux.c: for Linux platform 132 | * libhttpd/http_sys_w32.c: for Windows platform 133 | * libhttpd/http_urldecode.c: decode url-encode-wwww 134 | * libhttpd/http_urldecode.h: decode url-encode-wwww 135 | * libhttpd/http_urlencode.c: encode url-encode-www 136 | * libhttpd/http_urlencode.h: encode url-encode-www 137 | * libhttpd/libhttp.c: user interface 138 | * libhttpd/libhttp.h: user interface 139 | -------------------------------------------------------------------------------- /build/Makefile._gcc: -------------------------------------------------------------------------------- 1 | TOP_PATH = .. 2 | 3 | VPATH += $(TOP_PATH)/libsocket \ 4 | $(TOP_PATH)/libhttpd \ 5 | $(TOP_PATH)/test \ 6 | $(TOP_PATH)/duktape 7 | 8 | CFLAGS += -Wall -Werror \ 9 | -I $(TOP_PATH)/libsocket \ 10 | -I $(TOP_PATH)/libhttpd \ 11 | -I $(TOP_PATH)/duktape 12 | 13 | CFLAGS += -ggdb 14 | #LIBS += 15 | 16 | OBJS_DUKTAPE += \ 17 | $(OBJS_PATH)/duktape.o \ 18 | $(OBJS_PATH)/dukpylib.o 19 | 20 | OBJS_ALL += \ 21 | $(OBJS_DUKTAPE) \ 22 | $(OBJS_PATH)/http_string.o \ 23 | $(OBJS_PATH)/http_map.o \ 24 | $(OBJS_PATH)/http_content.o \ 25 | $(OBJS_PATH)/http_server.o \ 26 | $(OBJS_PATH)/http_client.o \ 27 | $(OBJS_PATH)/http_sendrecv.o \ 28 | $(OBJS_PATH)/http_parse.o \ 29 | $(OBJS_PATH)/http_urlencode.o \ 30 | $(OBJS_PATH)/http_urldecode.o \ 31 | $(OBJS_PATH)/http_mpm.o \ 32 | $(OBJS_PATH)/libhttp.o \ 33 | $(OBJS_PATH)/wsgi_server.o 34 | 35 | all:$(OBJS_PATH) \ 36 | shell.$(SUFFIX) \ 37 | shell2.$(SUFFIX) \ 38 | duk_server.$(SUFFIX) \ 39 | simple_server.$(SUFFIX) \ 40 | simple_client.$(SUFFIX) 41 | 42 | $(OBJS_PATH): 43 | @echo mkdir $(OBJS_PATH) 44 | $(MKDIR) $(OBJS_PATH) 45 | 46 | shell.$(SUFFIX):$(OBJS_PATH)/shell.o $(OBJS_DUKTAPE) 47 | @echo create $@ 48 | @gcc $(CFLAGS) $(LFLAGS) -L. $^ $(LIBS) -o $@ 49 | 50 | shell2.$(SUFFIX):$(OBJS_PATH)/shell2.o libhttpd.a 51 | @echo create $@ 52 | @gcc $(CFLAGS) $(LFLAGS) -L. $< -lhttpd $(LIBS) -o $@ 53 | 54 | duk_server.$(SUFFIX):$(OBJS_PATH)/duk_server.o libhttpd.a 55 | @echo create $@ 56 | @gcc $(CFLAGS) $(LFLAGS) -L. $< -lhttpd $(LIBS) -o $@ 57 | 58 | simple_server.$(SUFFIX):$(OBJS_PATH)/simple_server.o libhttpd.a 59 | @echo create $@ 60 | @gcc $(CFLAGS) $(LFLAGS) -L. $< -lhttpd $(LIBS) -o $@ 61 | 62 | simple_client.$(SUFFIX):$(OBJS_PATH)/simple_client.o libhttpd.a 63 | @echo create $@ 64 | @gcc $(CFLAGS) $(LFLAGS) -L. $< -lhttpd $(LIBS) -o $@ 65 | 66 | libhttpd.a:$(OBJS_ALL) 67 | @echo create $@ 68 | @rm -rf $@ 69 | @ar cr $@ $^ 70 | 71 | $(OBJS_PATH)/%.o:%.c 72 | @echo compiling $< 73 | @gcc $(CFLAGS) -c $< -o $@ 74 | 75 | clean: 76 | $(RM) -rf $(OBJS_PATH) 77 | $(RM) -rf *.o 78 | $(RM) -rf *.a 79 | $(RM) -rf *.$(SUFFIX) 80 | 81 | -------------------------------------------------------------------------------- /build/Makefile.linux: -------------------------------------------------------------------------------- 1 | MKDIR = mkdir 2 | RM = rm 3 | CFLAGS += -D TARGET_LINUX 4 | SUFFIX = elf 5 | OBJS_PATH = objs 6 | 7 | OBJS_DUKTAPE += \ 8 | $(OBJS_PATH)/subprocess_linux.o 9 | 10 | OBJS_ALL += $(OBJS_PATH)/usocket.o \ 11 | $(OBJS_PATH)/http_sys_linux.o 12 | 13 | LIBS += -lm -lpthread -lrt 14 | 15 | include Makefile._gcc 16 | 17 | -------------------------------------------------------------------------------- /build/Makefile.mingw: -------------------------------------------------------------------------------- 1 | MKDIR = mkdir.exe 2 | RM = rm.exe 3 | CFLAGS += -D TARGET_WINDOWS 4 | SUFFIX = exe 5 | OBJS_PATH = objs 6 | 7 | OBJS_DUKTAPE += \ 8 | $(OBJS_PATH)/subprocess_w32.o 9 | 10 | OBJS_ALL += $(OBJS_PATH)/wsocket.o \ 11 | $(OBJS_PATH)/http_sys_w32.o \ 12 | 13 | LIBS += -lws2_32 -lpsapi -liconv 14 | 15 | include Makefile._gcc 16 | 17 | -------------------------------------------------------------------------------- /build/Makefile.msvc: -------------------------------------------------------------------------------- 1 | TOP_PATH = .. 2 | OBJS_PATH = objs 3 | CFLAGS = /nologo /c \ 4 | /W3 /wd4996 \ 5 | /I . \ 6 | /I $(TOP_PATH)/libsocket \ 7 | /I $(TOP_PATH)/libhttpd \ 8 | /I $(TOP_PATH)/duktape \ 9 | /D TARGET_WINDOWS \ 10 | /Foobjs/ \ 11 | /Zi 12 | 13 | LFLAGS = /nologo /DEBUG 14 | 15 | LIBS = ws2_32.lib iconv/iconv.lib 16 | 17 | OBJS_DUKTAPE = \ 18 | $(OBJS_PATH)/duktape.obj \ 19 | $(OBJS_PATH)/dukpylib.obj \ 20 | $(OBJS_PATH)/subprocess_w32.obj 21 | 22 | OBJS_ALL = \ 23 | $(OBJS_DUKTAPE) \ 24 | $(OBJS_PATH)/http_string.obj \ 25 | $(OBJS_PATH)/http_map.obj \ 26 | $(OBJS_PATH)/http_content.obj \ 27 | $(OBJS_PATH)/http_server.obj \ 28 | $(OBJS_PATH)/http_client.obj \ 29 | $(OBJS_PATH)/http_sendrecv.obj \ 30 | $(OBJS_PATH)/http_parse.obj \ 31 | $(OBJS_PATH)/http_urlencode.obj \ 32 | $(OBJS_PATH)/http_urldecode.obj \ 33 | $(OBJS_PATH)/http_mpm.obj \ 34 | $(OBJS_PATH)/libhttp.obj \ 35 | $(OBJS_PATH)/wsgi_server.obj \ 36 | $(OBJS_PATH)/wsocket.obj \ 37 | $(OBJS_PATH)/http_sys_w32.obj \ 38 | 39 | 40 | all:$(OBJS_PATH) iconv/iconv.lib shell.exe 41 | 42 | $(OBJS_PATH): 43 | mkdir $(OBJS_PATH) 44 | 45 | iconv/iconv.lib:$(TOP_PATH)/iconv.lib.7z 46 | 7za x -oiconv $(TOP_PATH)/iconv.lib.7z 47 | touch iconv/iconv.lib 48 | 49 | all:$(OBJS_PATH) \ 50 | shell.exe \ 51 | shell2.exe \ 52 | duk_server.exe \ 53 | simple_server.exe \ 54 | simple_client.exe 55 | 56 | shell.exe:$(OBJS_PATH)/shell.obj $(OBJS_DUKTAPE) 57 | link $(LFLAGS) $(OBJS_PATH)/shell.obj $(OBJS_DUKTAPE) iconv/iconv.lib /out:$@ 58 | 59 | shell2.exe:$(OBJS_PATH)/shell2.obj httpd.lib 60 | link $(LFLAGS) $(OBJS_PATH)/shell2.obj httpd.lib $(LIBS) /out:$@ 61 | 62 | duk_server.exe:$(OBJS_PATH)/duk_server.obj httpd.lib 63 | link $(LFLAGS) $(OBJS_PATH)/duk_server.obj httpd.lib $(LIBS) /out:$@ 64 | 65 | simple_server.exe:$(OBJS_PATH)/simple_server.obj httpd.lib 66 | link $(LFLAGS) $(OBJS_PATH)/simple_server.obj httpd.lib $(LIBS) /out:$@ 67 | 68 | simple_client.exe:$(OBJS_PATH)/simple_client.obj httpd.lib 69 | link $(LFLAGS) $(OBJS_PATH)/simple_client.obj httpd.lib $(LIBS) /out:$@ 70 | 71 | httpd.lib:$(OBJS_ALL) 72 | lib /nologo $(OBJS_ALL) /out:httpd.lib 73 | 74 | 75 | {$(TOP_PATH)/duktape}.c{$(OBJS_PATH)}.obj: 76 | cl $(CFLAGS) $< 77 | 78 | {$(TOP_PATH)/libhttpd}.c{$(OBJS_PATH)}.obj: 79 | cl $(CFLAGS) $< 80 | 81 | {$(TOP_PATH)/libsocket}.c{$(OBJS_PATH)}.obj: 82 | cl $(CFLAGS) $< 83 | 84 | {$(TOP_PATH)/test}.c{$(OBJS_PATH)}.obj: 85 | cl $(CFLAGS) $< 86 | 87 | clean: 88 | rm -rf $(OBJS_PATH)/*.obj 89 | 90 | cleanall: 91 | rm -rf $(OBJS_PATH) 92 | rm -rf *.exe *.ilk *.pdb *.lib 93 | rm -rf iconv 94 | 95 | -------------------------------------------------------------------------------- /duktape/dukpylib.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #ifndef DUKPYLIB_H_FBD97D40_A148_11E5_97F3_001F160E9257_INCLUDED_ 27 | #define DUKPYLIB_H_FBD97D40_A148_11E5_97F3_001F160E9257_INCLUDED_ 28 | 29 | //linux maybe utf-8 30 | #ifdef DUK_F_WINDOWS 31 | #define DUKLIB_DEFAULT_SYSENCODING "GBK" 32 | #endif 33 | 34 | 35 | char* pylib_iconv(duk_context* ctx, const char* instr, int inlen, int* outlen, 36 | const char* inenc, const char* outenc); 37 | 38 | int pylib_include(duk_context* ctx, const char* fn); 39 | int pylib_eval_string(duk_context* ctx, const char* s); 40 | 41 | int pylib_put_args(duk_context* ctx, int argc, char* argv[]); 42 | 43 | //nr_vars DUK_VARARGS 44 | int pylib_put_c_method(duk_context* ctx, 45 | const char* function_name, 46 | duk_c_function function_entry); 47 | 48 | int pylib_put_c_function(duk_context* ctx, 49 | const char* function_name, 50 | duk_c_function function_entry); 51 | 52 | const char* pylib_type_name(duk_context* ctx, duk_idx_t index); 53 | 54 | //encode or decode string on stack[idx] 55 | int pylib_encode(duk_context* ctx, int idx, const char* encoding); 56 | int pylib_decode(duk_context* ctx, int idx, const char* encoding); 57 | 58 | 59 | int dukopen_pylib(duk_context* ctx); 60 | 61 | #endif 62 | 63 | -------------------------------------------------------------------------------- /duktape/subprocess.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #ifndef SUBPROCESS_H_F470BFDE_579D_11E5_A8CF_005056C00008_INCLUDED_ 27 | #define SUBPROCESS_H_F470BFDE_579D_11E5_A8CF_005056C00008_INCLUDED_ 28 | #include 29 | 30 | //example: 31 | // write(stdin_fileno, buffer, size) 32 | // read(stdout_fileno, buffer, size) 33 | typedef struct { 34 | void* proc; 35 | int pid; 36 | int stdin_fileno; 37 | int stdout_fileno; 38 | }subprocess_t; 39 | 40 | //windows: 41 | // file != NULL: file + " " + args[1] + " " + args[2] + " " + ... 42 | // file == NULL: args[0] + " " + args[1] + " " + args[2] + " " + ... 43 | // 44 | //linux: 45 | // execvp(file, args); 46 | // 47 | subprocess_t* psopen(char* file, char* args[]); 48 | 49 | //wait child exit or terminated, then close all handle. 50 | int pswait(subprocess_t* ps); 51 | 52 | //kill child if not exist nor terminated, then close all handle, and free all. 53 | void psclose(subprocess_t* ps); 54 | 55 | #endif 56 | 57 | -------------------------------------------------------------------------------- /duktape/subprocess_linux.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include 35 | #include 36 | #include 37 | 38 | #include "subprocess.h" 39 | 40 | // parent ---write---> pipe ---read---> child 41 | // inheritance heritance 42 | static int _create_pipe_stdin(int* stdin_rd, int* stdin_wr); 43 | 44 | // parent <---read--- pipe <---write--- child 45 | // inheritance heritance 46 | static int _create_pipe_stdout(int* stdout_rd, int* stdout_wr); 47 | 48 | 49 | int _create_pipe_stdin(int* stdin_rd, int* stdin_wr) 50 | { 51 | int h[2]; 52 | int h_rd; 53 | 54 | if (pipe(h) < 0) { 55 | return -1; 56 | } 57 | 58 | h_rd = dup(h[0]); 59 | close(h[0]); 60 | 61 | *stdin_rd = h_rd; 62 | *stdin_wr = h[1]; 63 | 64 | return 0; 65 | } 66 | 67 | int _create_pipe_stdout(int* stdout_rd, int* stdout_wr) 68 | { 69 | int h[2]; 70 | int h_wr; 71 | 72 | if (pipe(h) < 0) { 73 | return -1; 74 | } 75 | 76 | h_wr = dup(h[1]); 77 | close(h[1]); 78 | 79 | *stdout_rd = h[0]; 80 | *stdout_wr = h_wr; 81 | 82 | return 0; 83 | } 84 | 85 | subprocess_t* psopen(char* file, char* args[]) 86 | { 87 | subprocess_t* ps; 88 | pid_t pid; 89 | int stdin_wr; 90 | int stdin_rd; 91 | int stdout_wr; 92 | int stdout_rd; 93 | 94 | if (_create_pipe_stdin(&stdin_rd, &stdin_wr) < 0) { 95 | return NULL; 96 | } 97 | if (_create_pipe_stdout(&stdout_rd, &stdout_wr) < 0) { 98 | close(stdin_rd); 99 | close(stdin_wr); 100 | return NULL; 101 | } 102 | 103 | pid = vfork(); 104 | if (pid < 0) { 105 | close(stdin_rd); 106 | close(stdin_wr); 107 | close(stdout_rd); 108 | close(stdout_wr); 109 | return NULL; 110 | } 111 | 112 | if (pid == 0) { 113 | //_exit() do not flush then close standard I/O 114 | //so I just use exit() 115 | if (dup2(stdin_rd, STDIN_FILENO) < 0) { 116 | exit(-1); 117 | } 118 | if (dup2(stdout_wr, STDOUT_FILENO) < 0) { 119 | exit(-1); 120 | } 121 | execvp(args[0], args); 122 | exit(-1); 123 | } 124 | 125 | close(stdin_rd); 126 | close(stdout_wr); 127 | 128 | ps = (subprocess_t*)malloc(sizeof(subprocess_t)); 129 | ps->pid = pid; 130 | ps->proc = (void*)pid; 131 | ps->stdin_fileno = stdin_wr; 132 | ps->stdout_fileno = stdout_rd; 133 | 134 | return ps; 135 | } 136 | 137 | 138 | int pswait(subprocess_t* ps) 139 | { 140 | int status; 141 | int returncode = 0; 142 | 143 | if (ps->pid > 0) { 144 | if (waitpid(ps->pid , &status, 0) == -1) { 145 | returncode = -1; 146 | } else { 147 | returncode = (char)(status >> 8); 148 | } 149 | ps->pid = 0; 150 | 151 | close(ps->stdin_fileno); 152 | close(ps->stdout_fileno); 153 | } 154 | 155 | return returncode; 156 | } 157 | 158 | void psclose(subprocess_t* ps) 159 | { 160 | int i; 161 | int signals[] = {SIGINT, SIGTERM, SIGABRT, SIGKILL}; 162 | 163 | if (ps->pid > 0) { 164 | close(ps->stdin_fileno); 165 | close(ps->stdout_fileno); 166 | 167 | for (i = 0;i < sizeof(signals)/sizeof(signals[0]);i++) { 168 | if (kill(ps->pid, 0) == -1) { 169 | break; 170 | } 171 | kill(ps->pid, signals[i]); 172 | usleep(10 * 1000); 173 | } 174 | 175 | ps->pid = 0; 176 | } 177 | 178 | free(ps); 179 | } 180 | 181 | 182 | -------------------------------------------------------------------------------- /hashmap/hashmap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "hashmap.h" 32 | 33 | struct hashmap_list_t{ 34 | struct hashmap_list_t* next; 35 | char* key; 36 | char* data; 37 | }; 38 | 39 | struct hashmap_t{ 40 | int max_slot; 41 | int length; 42 | hashmap_list_t** slot; 43 | }; 44 | 45 | //modbus crc polygon. 46 | static unsigned short _crc_lut16[256] = { 47 | 0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 48 | 0x0280, 0xc241, 0xc601, 0x06c0, 0x0780, 0xc741, 49 | 0x0500, 0xc5c1, 0xc481, 0x0440, 0xcc01, 0x0cc0, 50 | 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40, 51 | 0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 52 | 0x0880, 0xc841, 0xd801, 0x18c0, 0x1980, 0xd941, 53 | 0x1b00, 0xdbc1, 0xda81, 0x1a40, 0x1e00, 0xdec1, 54 | 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41, 55 | 0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 56 | 0x1680, 0xd641, 0xd201, 0x12c0, 0x1380, 0xd341, 57 | 0x1100, 0xd1c1, 0xd081, 0x1040, 0xf001, 0x30c0, 58 | 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240, 59 | 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 60 | 0x3480, 0xf441, 0x3c00, 0xfcc1, 0xfd81, 0x3d40, 61 | 0xff01, 0x3fc0, 0x3e80, 0xfe41, 0xfa01, 0x3ac0, 62 | 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, 63 | 0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 64 | 0x2a80, 0xea41, 0xee01, 0x2ec0, 0x2f80, 0xef41, 65 | 0x2d00, 0xedc1, 0xec81, 0x2c40, 0xe401, 0x24c0, 66 | 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640, 67 | 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 68 | 0x2080, 0xe041, 0xa001, 0x60c0, 0x6180, 0xa141, 69 | 0x6300, 0xa3c1, 0xa281, 0x6240, 0x6600, 0xa6c1, 70 | 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441, 71 | 0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 72 | 0x6e80, 0xae41, 0xaa01, 0x6ac0, 0x6b80, 0xab41, 73 | 0x6900, 0xa9c1, 0xa881, 0x6840, 0x7800, 0xb8c1, 74 | 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, 75 | 0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 76 | 0xbc81, 0x7c40, 0xb401, 0x74c0, 0x7580, 0xb541, 77 | 0x7700, 0xb7c1, 0xb681, 0x7640, 0x7200, 0xb2c1, 78 | 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041, 79 | 0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 80 | 0x5280, 0x9241, 0x9601, 0x56c0, 0x5780, 0x9741, 81 | 0x5500, 0x95c1, 0x9481, 0x5440, 0x9c01, 0x5cc0, 82 | 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, 83 | 0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 84 | 0x5880, 0x9841, 0x8801, 0x48c0, 0x4980, 0x8941, 85 | 0x4b00, 0x8bc1, 0x8a81, 0x4a40, 0x4e00, 0x8ec1, 86 | 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41, 87 | 0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 88 | 0x4680, 0x8641, 0x8201, 0x42c0, 0x4380, 0x8341, 89 | 0x4100, 0x81c1, 0x8081, 0x4040 90 | }; 91 | 92 | static unsigned short _crc16(const void* buf, int len) 93 | { 94 | unsigned short r = 0xFFFF; 95 | const unsigned char* p; 96 | 97 | p = (const unsigned char*)buf; 98 | 99 | while (len-- > 0) { 100 | r = (_crc_lut16[(r & 0xFF) ^ (*p++)]) ^ ((r >> 8) & 0xFF); 101 | } 102 | 103 | return r; 104 | } 105 | 106 | hashmap_t* hashmap_create(int max_slot) 107 | { 108 | hashmap_t* m; 109 | int i; 110 | int mask = 0x10000; 111 | 112 | //make sure max_slot is pow(2,n) 113 | if (max_slot <= 0) { 114 | max_slot = 1; 115 | } else if (max_slot > 0x10000) { 116 | max_slot = 0x10000; 117 | } else { 118 | for (i = 0;i < 16;i++) { 119 | if (max_slot >= mask) { 120 | max_slot = mask; 121 | break; 122 | } 123 | mask >>= 1; 124 | } 125 | } 126 | 127 | m = (hashmap_t*)malloc(sizeof(hashmap_t)); 128 | memset(m, 0, sizeof(hashmap_t)); 129 | 130 | m->max_slot = max_slot; 131 | m->length = 0; 132 | m->slot = (hashmap_list_t**)malloc(sizeof(hashmap_list_t*)*max_slot); 133 | memset(m->slot, 0, sizeof(hashmap_list_t*)*max_slot); 134 | 135 | return m; 136 | } 137 | 138 | void hashmap_destroy(hashmap_t* m) 139 | { 140 | int i; 141 | hashmap_list_t* p; 142 | 143 | for (i = 0;i < m->max_slot;i++) { 144 | if (m->slot[i]) { 145 | while (m->slot[i]) { 146 | p = m->slot[i]; 147 | m->slot[i] = m->slot[i]->next; 148 | free(p->key); 149 | if (p->data) { 150 | free(p->data); 151 | } 152 | free(p); 153 | } 154 | } 155 | } 156 | 157 | free(m->slot); 158 | free(m); 159 | } 160 | 161 | int hashmap_set(hashmap_t* m, const char* k, const char* v) 162 | { 163 | unsigned short h; 164 | hashmap_list_t* prev; 165 | hashmap_list_t* p; 166 | 167 | h = _crc16(k, strlen(k)); 168 | h = h % m->max_slot; 169 | 170 | if (m->slot[h]) { 171 | for (p = m->slot[h];p != NULL;p = p->next) { 172 | if (strcmp(p->key, k) == 0) { 173 | if (p->data) { 174 | free(p->data); 175 | } 176 | p->data = strdup(v); 177 | return 0; 178 | } 179 | prev = p; 180 | } 181 | p = prev; 182 | p->next = (hashmap_list_t*)malloc(sizeof(hashmap_list_t)); 183 | p = p->next; 184 | memset(p, 0, sizeof(hashmap_list_t)); 185 | 186 | } else { 187 | p = (hashmap_list_t*)malloc(sizeof(hashmap_list_t)); 188 | memset(p, 0, sizeof(hashmap_list_t)); 189 | m->slot[h] = p; 190 | } 191 | 192 | p->key = strdup(k); 193 | p->data = strdup(v); 194 | m->length++; 195 | 196 | return 1; 197 | } 198 | 199 | const char* hashmap_get(hashmap_t* m, const char* k) 200 | { 201 | unsigned short h; 202 | hashmap_list_t* p; 203 | 204 | h = _crc16(k, strlen(k)); 205 | h = h % m->max_slot; 206 | 207 | if (!m->slot[h]) { 208 | return NULL; 209 | } 210 | 211 | for (p = m->slot[h];p != NULL;p = p->next) { 212 | if (strcmp(p->key, k) == 0) { 213 | return p->data; 214 | } 215 | } 216 | 217 | return NULL; 218 | } 219 | 220 | int hashmap_del(hashmap_t* m, const char* k) 221 | { 222 | unsigned short h; 223 | hashmap_list_t* prev; 224 | hashmap_list_t* p; 225 | 226 | h = _crc16(k, strlen(k)); 227 | h = h % m->max_slot; 228 | 229 | if (!m->slot[h]) { 230 | return 0; 231 | } 232 | 233 | prev = m->slot[h]; 234 | for (p = m->slot[h];p != NULL;p = p->next) { 235 | if (strcmp(p->key, k) == 0) { 236 | if (p == m->slot[h]) { 237 | m->slot[h] = p->next; 238 | } else { 239 | prev->next = p->next; 240 | } 241 | if (p->data) { 242 | free(p->data); 243 | } 244 | free(p->key); 245 | free(p); 246 | m->length--; 247 | return 1; 248 | } 249 | prev = p; 250 | } 251 | 252 | return 0; 253 | } 254 | 255 | void hashmap_dump(hashmap_t* m) 256 | { 257 | int i; 258 | hashmap_list_t* p; 259 | 260 | for (i = 0;i < m->max_slot;i++) { 261 | if (m->slot[i]) { 262 | printf("0x%04x: ", i); 263 | for (p = m->slot[i];p != NULL;p = p->next) { 264 | printf("\"%s\"", p->key); 265 | if (p->next != NULL) { 266 | printf(", "); 267 | } 268 | } 269 | printf("\n"); 270 | } 271 | } 272 | } 273 | 274 | void hashmap_begin(hashmap_t* m, hashmap_iter_t* iter) 275 | { 276 | int i; 277 | 278 | iter->m = m; 279 | iter->idx_slot = 0; 280 | iter->idx_list = NULL; 281 | iter->key = NULL; 282 | iter->data = NULL; 283 | 284 | if (m->length == 0) { 285 | return; 286 | } 287 | 288 | //find first element 289 | for (i = 0;i < m->max_slot;i++) { 290 | if (m->slot[i]) { 291 | break; 292 | } 293 | } 294 | 295 | iter->idx_slot = i; 296 | iter->idx_list = m->slot[i]; 297 | iter->key = iter->idx_list->key; 298 | iter->data = iter->idx_list->data; 299 | } 300 | 301 | int hashmap_valid(hashmap_iter_t* iter) 302 | { 303 | if (iter->key) { 304 | return 1; 305 | } 306 | 307 | return 0; 308 | } 309 | 310 | void hashmap_next(hashmap_iter_t* iter) 311 | { 312 | int i; 313 | hashmap_t* m; 314 | 315 | if (!iter->key) { 316 | return; 317 | } 318 | 319 | if (iter->idx_list->next) { 320 | iter->idx_list = iter->idx_list->next; 321 | iter->key = iter->idx_list->key; 322 | iter->data = iter->idx_list->data; 323 | return; 324 | } 325 | 326 | m = iter->m; 327 | i = iter->idx_slot+1; 328 | for (;i < m->max_slot;i++) { 329 | if (m->slot[i]) { 330 | break; 331 | } 332 | } 333 | 334 | if (i == m->max_slot) { 335 | iter->key = NULL; 336 | iter->data = NULL; 337 | return; 338 | } 339 | 340 | iter->idx_slot = i; 341 | iter->idx_list = m->slot[i]; 342 | iter->key = iter->idx_list->key; 343 | iter->data = iter->idx_list->data; 344 | } 345 | 346 | 347 | -------------------------------------------------------------------------------- /hashmap/hashmap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | * 25 | * 26 | * hashmap is better for huge elements. 27 | * when elements < 1000, just use array or simple list. 28 | * 29 | * performance and space blance: max_slot = elements / 40 30 | * 31 | */ 32 | 33 | #ifndef HASHMAP_H_4AA8FF5E_AA16_11E5_A7A8_005056C00008_INCLUDED_ 34 | #define HASHMAP_H_4AA8FF5E_AA16_11E5_A7A8_005056C00008_INCLUDED_ 35 | typedef struct hashmap_list_t hashmap_list_t; 36 | typedef struct hashmap_t hashmap_t; 37 | 38 | typedef struct hashmap_iter_t{ 39 | hashmap_t* m; 40 | int idx_slot; 41 | hashmap_list_t* idx_list; 42 | 43 | const char* key; 44 | const char* data; 45 | }hashmap_iter_t; 46 | 47 | 48 | hashmap_t* hashmap_create(int max_slot); 49 | void hashmap_destroy(hashmap_t* m); 50 | 51 | int hashmap_set(hashmap_t* m, const char* k, const char* v); 52 | const char* hashmap_get(hashmap_t* m, const char* k); 53 | int hashmap_del(hashmap_t* m, const char* k); 54 | 55 | void hashmap_dump(hashmap_t* m); 56 | 57 | void hashmap_begin(hashmap_t* m, hashmap_iter_t* iter); 58 | int hashmap_valid(hashmap_iter_t* iter); 59 | void hashmap_next(hashmap_iter_t* iter); 60 | 61 | 62 | #endif 63 | 64 | -------------------------------------------------------------------------------- /hashmap/hashmap.perf: -------------------------------------------------------------------------------- 1 | test iter: 2 | .key 1, .val fish 3 | .key 2, .val swordfish 4 | .key 4, .val berryfish 5 | .key 3, .val jewfish 6 | test performance: 7 | elements = 1000, slot = 65536, set = 0, get = 0, del = 0 8 | elements = 1000, slot = 32768, set = 0, get = 0, del = 0 9 | elements = 1000, slot = 16384, set = 0, get = 0, del = 0 10 | elements = 1000, slot = 8192, set = 0, get = 0, del = 0 11 | elements = 1000, slot = 4096, set = 0, get = 0, del = 0 12 | elements = 1000, slot = 2048, set = 0, get = 0, del = 0 13 | elements = 1000, slot = 1024, set = 0, get = 0, del = 0 14 | elements = 1000, slot = 512, set = 10, get = 0, del = 0 15 | elements = 1000, slot = 256, set = 0, get = 0, del = 0 16 | elements = 1000, slot = 128, set = 0, get = 0, del = 0 17 | elements = 1000, slot = 64, set = 0, get = 0, del = 0 18 | elements = 1000, slot = 32, set = 0, get = 0, del = 0 19 | elements = 1000, slot = 16, set = 0, get = 0, del = 0 20 | elements = 1000, slot = 8, set = 0, get = 10, del = 0 21 | elements = 1000, slot = 4, set = 0, get = 0, del = 0 22 | elements = 1000, slot = 2, set = 0, get = 10, del = 0 23 | elements = 1000, slot = 1, set = 0, get = 10, del = 0 24 | elements = 10000, slot = 65536, set = 10, get = 0, del = 0 25 | elements = 10000, slot = 32768, set = 10, get = 0, del = 0 26 | elements = 10000, slot = 16384, set = 10, get = 0, del = 0 27 | elements = 10000, slot = 8192, set = 10, get = 0, del = 0 28 | elements = 10000, slot = 4096, set = 10, get = 0, del = 0 29 | elements = 10000, slot = 2048, set = 10, get = 0, del = 0 30 | elements = 10000, slot = 1024, set = 0, get = 0, del = 10 31 | elements = 10000, slot = 512, set = 10, get = 0, del = 0 32 | elements = 10000, slot = 256, set = 10, get = 10, del = 0 33 | elements = 10000, slot = 128, set = 10, get = 0, del = 10 34 | elements = 10000, slot = 64, set = 20, get = 20, del = 10 35 | elements = 10000, slot = 32, set = 30, get = 30, del = 30 36 | elements = 10000, slot = 16, set = 60, get = 50, del = 60 37 | elements = 10000, slot = 8, set = 60, get = 50, del = 60 38 | elements = 10000, slot = 4, set = 110, get = 110, del = 120 39 | elements = 10000, slot = 2, set = 220, get = 210, del = 220 40 | elements = 10000, slot = 1, set = 360, get = 352, del = 370 41 | elements = 100000, slot = 65536, set = 40, get = 30, del = 30 42 | elements = 100000, slot = 32768, set = 50, get = 20, del = 40 43 | elements = 100000, slot = 16384, set = 40, get = 30, del = 40 44 | elements = 100000, slot = 8192, set = 50, get = 30, del = 50 45 | elements = 100000, slot = 4096, set = 50, get = 50, del = 50 46 | elements = 100000, slot = 2048, set = 80, get = 60, del = 80 47 | elements = 100000, slot = 1024, set = 110, get = 100, del = 110 48 | elements = 100000, slot = 512, set = 140, get = 130, del = 150 49 | elements = 100000, slot = 256, set = 240, get = 210, del = 230 50 | elements = 100000, slot = 128, set = 400, get = 380, del = 400 51 | elements = 100000, slot = 64, set = 730, get = 680, del = 720 52 | elements = 100000, slot = 32, set = 1460, get = 1394, del = 1460 53 | elements = 100000, slot = 16, set = 2930, get = 2830, del = 2920 54 | elements = 100000, slot = 8, set = 5620, get = 5440, del = 5625 55 | elements = 100000, slot = 4, set = 11102, get = 10712, del = 11026 56 | elements = 100000, slot = 2, set = 22098, get = 21196, del = 21972 57 | elements = 100000, slot = 1, set = 35995, get = 34616, del = 35147 58 | 59 | -------------------------------------------------------------------------------- /hashmap/hashmap_perf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "hashmap.h" 31 | 32 | void test_iter(void) 33 | { 34 | hashmap_t* m; 35 | hashmap_iter_t iter; 36 | 37 | m = hashmap_create(100); 38 | hashmap_set(m, "1", "fish"); 39 | hashmap_set(m, "2", "swordfish"); 40 | hashmap_set(m, "3", "jewfish"); 41 | hashmap_set(m, "4", "berryfish"); 42 | 43 | for (hashmap_begin(m, &iter);hashmap_valid(&iter);hashmap_next(&iter)) { 44 | printf(" .key %s, .val %s\n", iter.key, iter.data); 45 | } 46 | 47 | hashmap_destroy(m); 48 | } 49 | 50 | void test(int max_slot, int max_elements) 51 | { 52 | hashmap_t* m; 53 | int i; 54 | char key[16]; 55 | int count = max_elements; 56 | int N = 1; 57 | clock_t clk1; 58 | clock_t clk2; 59 | clock_t clk_set = 0; 60 | clock_t clk_get = 0; 61 | clock_t clk_del = 0; 62 | 63 | while (N--) { 64 | m = hashmap_create(max_slot); 65 | 66 | clk1 = clock(); 67 | for (i = 0;i < count;i++) { 68 | sprintf(key, "%08X", i); 69 | hashmap_set(m, key, key); 70 | } 71 | clk2 = clock(); 72 | clk_set += clk2 - clk1; 73 | 74 | clk1 = clock(); 75 | for (i = count-1;i >= 0;i--) { 76 | sprintf(key, "%08X", i); 77 | if (!hashmap_get(m, key)) { 78 | printf("Error not found when get \"%s\"\n", key); 79 | } 80 | } 81 | clk2 = clock(); 82 | clk_get += clk2 - clk1; 83 | 84 | clk1 = clock(); 85 | for (i = count-1;i >= 0;i--) { 86 | sprintf(key, "%08X", i); 87 | if (!hashmap_del(m, key)) { 88 | printf("Error not found when delete \"%s\"\n", key); 89 | } 90 | } 91 | clk2 = clock(); 92 | clk_del += clk2 - clk1; 93 | 94 | //hashmap_dump(m); 95 | hashmap_destroy(m); 96 | } 97 | 98 | printf(" elements = %8d, slot = %8d, set = %10d, get = %10d, del = %10d\n", 99 | max_elements, max_slot, 100 | (int)clk_set, (int)clk_get, (int)clk_del); 101 | } 102 | 103 | int main(int argc, char* argv[]) 104 | { 105 | int max_elements; 106 | int max_slot; 107 | 108 | printf("test iter:\n"); 109 | test_iter(); 110 | 111 | printf("test performance:\n"); 112 | for (max_elements = 1000;max_elements <= 100000;max_elements*=10) { 113 | for (max_slot = 0x10000;max_slot >= 1;max_slot >>= 1) { 114 | test(max_slot, max_elements); 115 | } 116 | } 117 | 118 | return 0; 119 | } 120 | 121 | -------------------------------------------------------------------------------- /iconv.lib.7z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buaabyl/dukserver/5e44cbc035134b62981774128cf7c82c355fa87a/iconv.lib.7z -------------------------------------------------------------------------------- /libhttpd/http_buffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #ifndef HTTP_BUFFER_H_66A3A130_8F30_11E5_97D9_005056C00008_INCLUDED_ 27 | #define HTTP_BUFFER_H_66A3A130_8F30_11E5_97D9_005056C00008_INCLUDED_ 28 | 29 | typedef struct _http_buffer_t { 30 | char* buf; 31 | int maxsize; 32 | int size; 33 | } http_buffer_t; 34 | 35 | typedef struct _http_reference_t { 36 | char* ptr; 37 | int size; 38 | } http_reference_t; 39 | 40 | #endif 41 | 42 | -------------------------------------------------------------------------------- /libhttpd/http_client.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "libsocket.h" 33 | 34 | #include "http_common.h" 35 | #include "http_sys.h" 36 | #include "http_string.h" 37 | #include "http_connection.h" 38 | #include "http_client.h" 39 | 40 | http_connection_t* http_connect(const char* host, const char* ip, unsigned short port) 41 | { 42 | http_connection_t* conn; 43 | socklen_t cli_len; 44 | int err; 45 | 46 | if (ip == NULL) { 47 | return NULL; 48 | } 49 | 50 | conn = (http_connection_t*)http_malloc(sizeof(http_connection_t)); 51 | conn->port = port; 52 | if (host != NULL) { 53 | conn->host = http_strdup(host); 54 | } else { 55 | conn->host = http_strdup(ip); 56 | } 57 | conn->handle = (socket_t*)http_malloc(sizeof(socket_t)); 58 | 59 | if (socket_create(conn->handle, AF_INET, SOCK_STREAM, IPPROTO_TCP) != IO_DONE) { 60 | http_free(conn->handle); 61 | http_free(conn); 62 | return NULL; 63 | } 64 | 65 | conn->addr.sin_addr.s_addr = inet_addr(ip); 66 | conn->addr.sin_family = AF_INET; 67 | conn->addr.sin_port = htons(port); 68 | cli_len = sizeof(conn->addr); 69 | 70 | err = socket_connect(conn->handle, 71 | (sockaddr*)&conn->addr, cli_len, 2); 72 | if (err != IO_DONE) { 73 | printf("Socket Error %d\n", err); 74 | socket_destroy(conn->handle); 75 | http_free(conn->host); 76 | http_free(conn->handle); 77 | http_free(conn); 78 | return NULL; 79 | } 80 | 81 | return conn; 82 | } 83 | 84 | void http_close(http_connection_t* conn) 85 | { 86 | socket_shutdown(conn->handle, SD_BOTH); 87 | http_free(conn->host); 88 | socket_destroy(conn->handle); 89 | http_free(conn->handle); 90 | http_free(conn); 91 | } 92 | 93 | -------------------------------------------------------------------------------- /libhttpd/http_client.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #ifndef HTTP_CLIENT_H_AE7D1F8F_8DB9_11E5_8987_005056C00008_INCLUDED_ 27 | #define HTTP_CLIENT_H_AE7D1F8F_8DB9_11E5_8987_005056C00008_INCLUDED_ 28 | 29 | //@param host NULL or "www.example.com" 30 | //@param ip "127.0.0.1" 31 | http_connection_t* http_connect(const char* host, const char* ip, unsigned short port); 32 | void http_close(http_connection_t* conn); 33 | 34 | #endif 35 | 36 | -------------------------------------------------------------------------------- /libhttpd/http_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #ifndef HTTP_COMMON_H_2CD7AE4F_8F31_11E5_8D78_005056C00008_INCLUDED_ 27 | #define HTTP_COMMON_H_2CD7AE4F_8F31_11E5_8D78_005056C00008_INCLUDED_ 28 | 29 | 30 | #define HTTP_DEFAULT_SERVER "libhttpd/1.0.0" 31 | #define HTTP_DEFAULT_CONTENT_TYPE "text/plain; charset=UTF-8" 32 | #define HTTP_DEFAULT_FORM_ENCODED "application/x-www-form-urlencoded" 33 | 34 | #define HTTP_DEFAULT_RESPONSE_EXPECT100 "HTTP/1.1 100 Continue\r\n\r\n" 35 | 36 | //parsed result of "request line" 37 | //also store in headers, 38 | //but the key name is below: //request response 39 | #define HTTP_METHOD " METHOD" // Y 40 | #define HTTP_URL " URL" // Y 41 | #define HTTP_SENDFILE " SENDFILE" // Y 42 | #define HTTP_VERSION " VERSION" // Y Y 43 | #define HTTP_TMPFILE " TMPFILE" // Y Y 44 | #define HTTP_STATUS " STATUS" // Y 45 | #define HTTP_MESSAGE " MESSAGE" // Y 46 | 47 | //when reach this, restart fastcgi thread 48 | #define HTTP_MPM_MAX_REQUESTS 1000 49 | 50 | #define HTTP_DEFAULT_HEADERS_COUNT 1000 51 | 52 | #define HTTP_ACCEPT_TIMEOUT 1 //second 53 | #define HTTP_SEND_TIMEOUT 1 //second 54 | #define HTTP_RECV_TIMEOUT 2 //second 55 | 56 | #define HTTP_MPM_FASTCGI_TIMEOUT 100 //ms 57 | 58 | #define K_BUFFER_1KB 0x400 59 | #define K_BUFFER_1MB 0x100000 60 | 61 | #define HTTP_MAX_BUFFER_SIZE (10 * K_BUFFER_1KB) 62 | #define HTTP_MAX_SEND_BLOCK (2 * K_BUFFER_1MB) 63 | 64 | 65 | 66 | #endif 67 | 68 | -------------------------------------------------------------------------------- /libhttpd/http_connection.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #ifndef HT_CONNECTION_H_B03B471E_8DB5_11E5_82CF_005056C00008_INCLUDED_ 27 | #define HT_CONNECTION_H_B03B471E_8DB5_11E5_82CF_005056C00008_INCLUDED_ 28 | 29 | //typedef socket_t http_socket_t; 30 | //typedef struct sockaddr_in http_sockaddr_t; 31 | 32 | typedef struct _http_connection_t{ 33 | char* host; 34 | int port; 35 | socket_t* handle; 36 | struct sockaddr_in addr; 37 | }http_connection_t; 38 | 39 | #endif 40 | 41 | -------------------------------------------------------------------------------- /libhttpd/http_content.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include "http_common.h" 31 | #include "http_sys.h" 32 | #include "http_string.h" 33 | #include "http_map.h" 34 | #include "http_buffer.h" 35 | #include "http_content.h" 36 | 37 | http_content_t* http_content_new(void) 38 | { 39 | http_content_t* ct; 40 | 41 | ct = (http_content_t*)http_malloc(sizeof(http_content_t)); 42 | memset(ct, 0, sizeof(http_content_t)); 43 | 44 | ct->headerbuf = (http_buffer_t*)http_malloc(sizeof(http_buffer_t)); 45 | ct->headerbuf->buf = (char*)http_malloc(HTTP_MAX_BUFFER_SIZE); 46 | ct->headerbuf->maxsize = HTTP_MAX_BUFFER_SIZE; 47 | ct->headerbuf->size = 0; 48 | 49 | ct->header = (http_reference_t*)http_malloc(sizeof(http_reference_t)); 50 | memset(ct->header, 0, sizeof(http_reference_t)); 51 | ct->body = (http_reference_t*)http_malloc(sizeof(http_reference_t)); 52 | memset(ct->body, 0, sizeof(http_reference_t)); 53 | 54 | ct->bodybuf = (http_buffer_t*)http_malloc(sizeof(http_buffer_t)); 55 | ct->bodybuf->buf = (char*)http_malloc(HTTP_MAX_BUFFER_SIZE); 56 | ct->bodybuf->maxsize = HTTP_MAX_BUFFER_SIZE; 57 | ct->bodybuf->size = 0; 58 | 59 | ct->dict = http_map_new(HTTP_DEFAULT_HEADERS_COUNT); 60 | 61 | return ct; 62 | } 63 | 64 | void http_content_delete(http_content_t* ct) 65 | { 66 | const char* tmpfilename_str; 67 | FILE* fp; 68 | 69 | if (ct == NULL) { 70 | printf("http_content_delete error\n"); 71 | } 72 | 73 | tmpfilename_str = http_map_get(ct->dict, HTTP_TMPFILE); 74 | if (tmpfilename_str != NULL) { 75 | if ((fp = fopen(tmpfilename_str, "r")) != NULL) { 76 | printf("remove \"%s\"\n", tmpfilename_str); 77 | fclose(fp); 78 | remove(tmpfilename_str); 79 | } 80 | } 81 | 82 | http_free(ct->headerbuf->buf); 83 | ct->headerbuf->buf = NULL; 84 | http_free(ct->headerbuf); 85 | ct->headerbuf = NULL; 86 | 87 | http_free(ct->header); 88 | ct->header = NULL; 89 | 90 | http_free(ct->body); 91 | ct->body = NULL; 92 | 93 | http_free(ct->bodybuf->buf); 94 | ct->bodybuf->buf = NULL; 95 | http_free(ct->bodybuf); 96 | ct->bodybuf = NULL; 97 | 98 | http_map_delete(ct->dict); 99 | ct->dict = NULL; 100 | 101 | http_free(ct); 102 | } 103 | 104 | void http_dump_content(http_content_t* ct) 105 | { 106 | int i; 107 | char c; 108 | const char* tmpfilename_str; 109 | http_map_iter_t iter; 110 | 111 | printf("[DUMP]\n"); 112 | for (http_map_begin(ct->dict, &iter); 113 | http_map_valid(&iter); 114 | http_map_next(&iter)) 115 | { 116 | printf("%s:%s\n", iter.k, iter.v); 117 | } 118 | printf("\n"); 119 | 120 | if (ct->body->ptr) { 121 | for (i = 0;i < ct->body->size;i++) { 122 | c = ct->body->ptr[i]; 123 | if (c == '\r') { 124 | printf("\\r"); 125 | } else if (c == '\n') { 126 | printf("\\n\n"); 127 | } else { 128 | printf("%c", c); 129 | } 130 | } 131 | 132 | } else { 133 | tmpfilename_str = http_map_get(ct->dict, HTTP_TMPFILE); 134 | if (tmpfilename_str != NULL) { 135 | printf("[FILE]\"%s\"\n", tmpfilename_str); 136 | } 137 | } 138 | printf("[EOF]\n"); 139 | } 140 | 141 | -------------------------------------------------------------------------------- /libhttpd/http_content.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #ifndef HTTP_CONTENT_H_8C3CDFB0_8F30_11E5_8033_005056C00008_INCLUDED_ 27 | #define HTTP_CONTENT_H_8C3CDFB0_8F30_11E5_8033_005056C00008_INCLUDED_ 28 | 29 | typedef struct _http_content_t { 30 | http_buffer_t* headerbuf; 31 | http_buffer_t* bodybuf; 32 | 33 | http_reference_t* header; 34 | http_reference_t* body; 35 | 36 | http_map_t* dict; 37 | } http_content_t; 38 | 39 | http_content_t* http_content_new(void); 40 | void http_content_delete(http_content_t* ct); 41 | 42 | void http_dump_content(http_content_t* ct); 43 | 44 | #endif 45 | 46 | -------------------------------------------------------------------------------- /libhttpd/http_map.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include "http_common.h" 31 | #include "http_sys.h" 32 | #include "http_string.h" 33 | #include "http_map.h" 34 | 35 | http_map_t* http_map_new(int maxcount) 36 | { 37 | http_map_t* m; 38 | 39 | if (maxcount <= 0) { 40 | return NULL; 41 | } 42 | 43 | m = (http_map_t*)http_malloc(sizeof(http_map_t)); 44 | m->max_count = maxcount; 45 | m->count = 0; 46 | m->values = (http_pair_t*)http_malloc(sizeof(http_pair_t)*maxcount); 47 | memset(m->values, 0, sizeof(http_pair_t)*maxcount); 48 | 49 | return m; 50 | } 51 | 52 | void http_map_delete(http_map_t* m) 53 | { 54 | int i; 55 | http_pair_t* p; 56 | 57 | if (m == NULL) { 58 | return; 59 | } 60 | 61 | for (i = 0;i < m->count;i++) { 62 | p = &m->values[i]; 63 | if (p->a) { 64 | http_free(p->a); 65 | p->a = NULL; 66 | } 67 | if (p->b) { 68 | http_free(p->b); 69 | p->b = NULL; 70 | } 71 | } 72 | 73 | http_free(m->values); 74 | m->values = NULL; 75 | 76 | http_free(m); 77 | m = NULL; 78 | } 79 | 80 | http_pair_t* http_map_set(http_map_t* m, const char* k, const char* v) 81 | { 82 | int i; 83 | int max_count; 84 | http_pair_t* p; 85 | 86 | if ((m == NULL) || (k == NULL)) { 87 | return NULL; 88 | } 89 | 90 | //expand buffer 91 | if (m->count + 1 >= m->max_count) { 92 | max_count = m->max_count * 2; 93 | m->values = (http_pair_t*)http_realloc( 94 | m->values, sizeof(http_pair_t) * max_count); 95 | for (i = m->max_count;i < max_count;i++) { 96 | p = &m->values[i]; 97 | p->a = NULL; 98 | p->b = NULL; 99 | } 100 | m->max_count = max_count; 101 | } 102 | 103 | //lookup duplicated key name 104 | for (i = 0;i < m->count;i++) { 105 | p = &m->values[i]; 106 | if (strcmp(k, p->a) == 0) { 107 | if (p->b) { 108 | http_free(p->b); 109 | p->b = NULL; 110 | } 111 | if (v != NULL) { 112 | p->b = http_strdup(v); 113 | } 114 | return p; 115 | } 116 | } 117 | 118 | p = &m->values[m->count++]; 119 | p->a = http_strdup(k); 120 | p->b = NULL; 121 | if (v != NULL) { 122 | p->b = http_strdup(v); 123 | } 124 | 125 | return p; 126 | } 127 | 128 | const char* http_map_get(http_map_t* m, const char* k) 129 | { 130 | int i; 131 | http_pair_t* p; 132 | 133 | if ((m == NULL) || (k == NULL) || (m->count <= 0)) { 134 | return NULL; 135 | } 136 | 137 | for (i = 0;i < m->count;i++) { 138 | p = &m->values[i]; 139 | if (strcmp(k, p->a) == 0) { 140 | return p->b; 141 | } 142 | } 143 | 144 | return NULL; 145 | } 146 | 147 | http_bool_t http_map_erase(http_map_t* m, const char* k) 148 | { 149 | int i; 150 | http_pair_t* p; 151 | 152 | if ((m == NULL) || (k == NULL) || (m->count <= 0)) { 153 | return HTTP_FALSE; 154 | } 155 | 156 | //lookup 157 | for (i = 0;i < m->count;i++) { 158 | p = &m->values[i]; 159 | if (strcmp(k, p->a) == 0) { 160 | break; 161 | } 162 | } 163 | if (i == m->count) { 164 | return HTTP_FALSE; 165 | } 166 | 167 | //found, so delete it 168 | if (p->b) { 169 | http_free(p->b); 170 | p->b = NULL; 171 | } 172 | http_free(p->a); 173 | p->a = NULL; 174 | 175 | //move 176 | for (;i < m->count-1;i++) { 177 | m->values[i].a = m->values[i+1].a; 178 | m->values[i].b = m->values[i+1].b; 179 | } 180 | m->values[m->count-1].a = NULL; 181 | m->values[m->count-1].b = NULL; 182 | m->count--; 183 | 184 | return HTTP_TRUE; 185 | } 186 | 187 | int http_map_count(http_map_t* m) 188 | { 189 | return m->count; 190 | } 191 | 192 | http_bool_t http_map_begin(http_map_t* m, http_map_iter_t* iter) 193 | { 194 | if (m->count <= 0) { 195 | iter->parent= NULL; 196 | iter->index = -1; 197 | iter->k = NULL; 198 | iter->v = NULL; 199 | return HTTP_FALSE; 200 | } 201 | 202 | iter->parent = m; 203 | iter->index = 0; 204 | iter->k = m->values[0].a; 205 | iter->v = m->values[0].b; 206 | 207 | return HTTP_TRUE; 208 | } 209 | 210 | http_bool_t http_map_valid(http_map_iter_t* iter) 211 | { 212 | if (iter->index < 0) { 213 | return HTTP_FALSE; 214 | } 215 | 216 | return HTTP_TRUE; 217 | } 218 | 219 | http_bool_t http_map_next(http_map_iter_t* iter) 220 | { 221 | if (iter->index == -1) { 222 | return HTTP_FALSE; 223 | } 224 | if (iter->index >= iter->parent->count - 1) { 225 | iter->index = -1; 226 | return HTTP_FALSE; 227 | } 228 | 229 | iter->index++; 230 | iter->k = iter->parent->values[iter->index].a; 231 | iter->v = iter->parent->values[iter->index].b; 232 | 233 | return HTTP_TRUE; 234 | } 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | -------------------------------------------------------------------------------- /libhttpd/http_map.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | /* 27 | * first implement is hashlib, but it is useless. 28 | * so I decided to use array. 29 | * 30 | * this implement sometime act as std::vector, 31 | * user alloc initial size, when overflow, resize 2 bigger. 32 | * 33 | */ 34 | 35 | #ifndef HTTP_MAP_H_08F5BCCF_8E6D_11E5_88A5_005056C00008_INCLUDED_ 36 | #define HTTP_MAP_H_08F5BCCF_8E6D_11E5_88A5_005056C00008_INCLUDED_ 37 | 38 | //////////////////////////////////////////////////////////// 39 | typedef struct _http_pair_t{ 40 | char* a; 41 | char* b; 42 | }http_pair_t; 43 | 44 | typedef struct _http_map_t{ 45 | int max_count; 46 | int count; 47 | http_pair_t* values; 48 | }http_map_t; 49 | 50 | http_map_t* http_map_new(int maxcount); 51 | void http_map_delete(http_map_t* m); 52 | http_pair_t* http_map_set(http_map_t* m, const char* k, const char* v); 53 | const char* http_map_get(http_map_t* m, const char* k); 54 | http_bool_t http_map_erase(http_map_t* m, const char* k); 55 | int http_map_count(http_map_t* m); 56 | 57 | //////////////////////////////////////////////////////////// 58 | typedef struct _http_map_iter_t{ 59 | http_map_t* parent; 60 | 61 | int index; 62 | const char* k; 63 | const char* v; 64 | }http_map_iter_t; 65 | 66 | http_bool_t http_map_begin(http_map_t* m, http_map_iter_t* iter); 67 | http_bool_t http_map_valid(http_map_iter_t* iter); 68 | http_bool_t http_map_next(http_map_iter_t* iter); 69 | 70 | #endif 71 | 72 | -------------------------------------------------------------------------------- /libhttpd/http_mpm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "libsocket.h" 33 | 34 | #include "http_common.h" 35 | #include "http_sys.h" 36 | #include "http_string.h" 37 | #include "http_map.h" 38 | #include "http_buffer.h" 39 | #include "http_content.h" 40 | #include "http_connection.h" 41 | #include "http_server.h" 42 | #include "http_sendrecv.h" 43 | #include "http_parse.h" 44 | 45 | #include "http_urlencode.h" 46 | #include "http_urldecode.h" 47 | 48 | #include "http_mpm.h" 49 | 50 | struct http_mpm_handle_t 51 | { 52 | //////////////////////////////////// 53 | //created by main thread 54 | //delete by main thread 55 | httpd_server_t* srv; 56 | 57 | http_sys_handle_t* event_break_accepter; 58 | http_sys_handle_t* event_break_fastcgi; 59 | http_sys_handle_t* event_accepter_exit; 60 | http_sys_handle_t* event_fastcgi_exit; 61 | 62 | http_sys_handle_t* mutex_fastcgi; 63 | http_sys_handle_t* event_fire; 64 | http_sys_handle_t* event_done; 65 | 66 | //created by main thread, 67 | //delete by frontend 68 | http_connection_t* conn; 69 | 70 | //////////////////////////////////// 71 | //created by frontend 72 | //delete by frontend 73 | http_content_t** req; 74 | 75 | //created by fastcgi 76 | //delete by frontend 77 | http_content_t** res; 78 | 79 | //////////////////////////////////// 80 | //for fastcgi 81 | http_mpm_initialize_cb initialize_cb; 82 | http_mpm_finalize_cb finialize_cb; 83 | http_mpm_process_cb process_cb; 84 | void* param; 85 | 86 | }; 87 | 88 | static void _worker_fastcgi(void* param); 89 | static void _worker_frontend(void* param); 90 | static void _worker_accepter(void* param); 91 | 92 | 93 | void _worker_fastcgi(void* param) 94 | { 95 | http_mpm_handle_t* cfg; 96 | http_content_t* req = NULL; 97 | http_content_t* res = NULL; 98 | http_sys_handle_t* event_exit; 99 | int fastcgi_break = HTTP_FALSE; 100 | int nr_request = 0; 101 | 102 | cfg = (http_mpm_handle_t*)param; 103 | 104 | while (!fastcgi_break) { 105 | if (http_event_trywait(cfg->event_break_fastcgi)) { 106 | break; 107 | } 108 | 109 | cfg->initialize_cb(cfg->param); 110 | 111 | for (nr_request = 0;nr_request < HTTP_MPM_MAX_REQUESTS;nr_request++) { 112 | if (http_event_trywait(cfg->event_break_fastcgi)) { 113 | fastcgi_break = HTTP_TRUE; 114 | break; 115 | } 116 | 117 | if (!http_event_waittimeout(cfg->event_fire, HTTP_MPM_FASTCGI_TIMEOUT)) { 118 | continue; 119 | } 120 | 121 | req = *(cfg->req); 122 | res = cfg->process_cb(cfg->param, req); 123 | *(cfg->res) = res; 124 | 125 | http_event_set(cfg->event_done); 126 | } 127 | 128 | cfg->finialize_cb(cfg->param); 129 | } 130 | 131 | event_exit = cfg->event_fastcgi_exit; 132 | http_free(cfg); 133 | http_event_set(event_exit); 134 | 135 | http_end_thread(); 136 | } 137 | 138 | void _worker_frontend(void* param) 139 | { 140 | http_mpm_handle_t* cfg = NULL; 141 | http_content_t* req = NULL; 142 | http_content_t* res = NULL; 143 | char remote_port[10]; 144 | const char* version; 145 | http_bool_t fastcgi_break = HTTP_FALSE; 146 | 147 | cfg = (http_mpm_handle_t*)param; 148 | 149 | while(!fastcgi_break) { 150 | //receive one request. 151 | req = http_recv_request(cfg->conn); 152 | if (req == NULL) { 153 | break; 154 | } 155 | 156 | //prepare connection information 157 | http_map_set(req->dict, "REMOTE_ADDR", cfg->conn->host); 158 | 159 | sprintf(remote_port, "%d", cfg->conn->port); 160 | http_map_set(req->dict, "REMOTE_PORT", remote_port); 161 | 162 | //send to fastcgi thread 163 | if (http_mutex_take(cfg->mutex_fastcgi)) { 164 | *(cfg->req) = req; 165 | http_event_set(cfg->event_fire); 166 | 167 | if (http_event_wait(cfg->event_done)) { 168 | res = *(cfg->res); 169 | *(cfg->res) = NULL; 170 | } 171 | 172 | http_mutex_give(cfg->mutex_fastcgi); 173 | 174 | } else { 175 | printf("_worker_frontend mutex timeout!\n"); 176 | } 177 | 178 | if (res == NULL) { 179 | res = http_content_new(); 180 | http_start_response(res, 500); 181 | http_write(res, "Fastcgi Error", 13); 182 | fastcgi_break = HTTP_TRUE; 183 | } 184 | 185 | //send response 186 | http_send_response(cfg->conn, res); 187 | http_content_delete(res); 188 | res = NULL; 189 | 190 | //check http version 191 | version = http_map_get(req->dict, HTTP_VERSION); 192 | if (version && (strcmp(version, "HTTP/1.0") == 0)) { 193 | fastcgi_break = HTTP_TRUE; 194 | } 195 | http_content_delete(req); 196 | req = NULL; 197 | } 198 | 199 | httpd_close(cfg->conn); 200 | cfg->conn = NULL; 201 | 202 | http_free(cfg); 203 | 204 | http_end_thread(); 205 | } 206 | 207 | void _worker_accepter(void* param) 208 | { 209 | http_mpm_handle_t* oldcfg = NULL; 210 | http_mpm_handle_t* cfg = NULL; 211 | http_connection_t* conn = NULL; 212 | http_content_t* interwork_req = NULL; 213 | http_content_t* interwork_res = NULL; 214 | http_sys_handle_t* event_exit; 215 | 216 | oldcfg = (http_mpm_handle_t*)param; 217 | 218 | cfg = (http_mpm_handle_t*)http_malloc(sizeof(http_mpm_handle_t)); 219 | cfg->srv = NULL; 220 | cfg->event_break_accepter = NULL; 221 | cfg->event_break_fastcgi = oldcfg->event_break_fastcgi; 222 | cfg->event_accepter_exit = NULL; 223 | cfg->event_fastcgi_exit = oldcfg->event_fastcgi_exit; 224 | 225 | cfg->mutex_fastcgi = NULL; 226 | cfg->event_fire = oldcfg->event_fire; 227 | cfg->event_done = oldcfg->event_done; 228 | cfg->conn = NULL; 229 | cfg->req = &interwork_req; 230 | cfg->res = &interwork_res; 231 | cfg->initialize_cb = oldcfg->initialize_cb; 232 | cfg->finialize_cb = oldcfg->finialize_cb; 233 | cfg->process_cb = oldcfg->process_cb; 234 | cfg->param = oldcfg->param; 235 | http_begin_thread(_worker_fastcgi, cfg); 236 | 237 | while (1) { 238 | if (http_event_trywait(oldcfg->event_break_accepter)) { 239 | break; 240 | } 241 | 242 | conn = httpd_accept(oldcfg->srv); 243 | if (conn == NULL) { 244 | continue; 245 | } 246 | 247 | cfg = (http_mpm_handle_t*)http_malloc(sizeof(http_mpm_handle_t)); 248 | cfg->event_break_accepter = NULL; 249 | cfg->event_break_fastcgi = NULL; 250 | cfg->event_accepter_exit = NULL; 251 | cfg->event_fastcgi_exit = NULL; 252 | 253 | cfg->mutex_fastcgi = oldcfg->mutex_fastcgi; 254 | cfg->event_fire = oldcfg->event_fire; 255 | cfg->event_done = oldcfg->event_done; 256 | cfg->conn = conn; 257 | cfg->req = &interwork_req; 258 | cfg->res = &interwork_res; 259 | cfg->initialize_cb = NULL; 260 | cfg->finialize_cb = NULL; 261 | cfg->process_cb = NULL; 262 | cfg->param = NULL; 263 | http_begin_thread(_worker_frontend, cfg); 264 | } 265 | 266 | event_exit = oldcfg->event_accepter_exit; 267 | http_free(oldcfg); 268 | http_event_set(event_exit); 269 | 270 | http_end_thread(); 271 | } 272 | 273 | http_mpm_handle_t* http_mpm_create(char* ip, int port) 274 | { 275 | http_mpm_handle_t* h = NULL; 276 | httpd_server_t* srv = NULL; 277 | 278 | srv = httpd_create(NULL, ip, port); 279 | if (srv == NULL) { 280 | printf("Can't create httpd!\n"); 281 | return NULL; 282 | } 283 | 284 | h = (http_mpm_handle_t*)http_malloc(sizeof(http_mpm_handle_t)); 285 | 286 | h->srv = srv; 287 | h->event_break_accepter = http_event_new(); 288 | h->event_break_fastcgi = http_event_new(); 289 | h->event_accepter_exit = http_event_new(); 290 | h->event_fastcgi_exit = http_event_new(); 291 | 292 | h->mutex_fastcgi = http_mutex_new(); 293 | h->event_fire = http_event_new(); 294 | h->event_done = http_event_new(); 295 | 296 | h->conn = NULL; 297 | h->req = NULL; 298 | h->res = NULL; 299 | 300 | h->initialize_cb = NULL; 301 | h->finialize_cb = NULL; 302 | h->process_cb = NULL; 303 | h->param = NULL; 304 | 305 | return h; 306 | } 307 | 308 | void http_mpm_set_initialize( 309 | http_mpm_handle_t* h, 310 | http_mpm_initialize_cb cb, 311 | void* initparam) 312 | { 313 | h->initialize_cb = cb; 314 | h->param= initparam; 315 | } 316 | 317 | void http_mpm_set_finalize( 318 | http_mpm_handle_t* h, 319 | http_mpm_finalize_cb cb) 320 | { 321 | h->finialize_cb = cb; 322 | } 323 | 324 | void http_mpm_set_process( 325 | http_mpm_handle_t* h, 326 | http_mpm_process_cb cb) 327 | { 328 | h->process_cb = cb; 329 | } 330 | 331 | http_bool_t http_mpm_start(http_mpm_handle_t* h) 332 | { 333 | http_mpm_handle_t* cfg = NULL; 334 | 335 | if (!h || (!h->process_cb)) { 336 | return HTTP_FALSE; 337 | } 338 | 339 | cfg = (http_mpm_handle_t*)http_malloc(sizeof(http_mpm_handle_t)); 340 | cfg->srv = h->srv; 341 | cfg->event_break_accepter = h->event_break_accepter; 342 | cfg->event_break_fastcgi = h->event_break_fastcgi; 343 | cfg->event_accepter_exit = h->event_accepter_exit; 344 | cfg->event_fastcgi_exit = h->event_fastcgi_exit; 345 | 346 | cfg->mutex_fastcgi = h->mutex_fastcgi; 347 | cfg->event_fire = h->event_fire; 348 | cfg->event_done = h->event_done; 349 | 350 | cfg->conn = NULL; 351 | cfg->req = NULL; 352 | cfg->res = NULL; 353 | 354 | cfg->initialize_cb = h->initialize_cb; 355 | cfg->finialize_cb = h->finialize_cb; 356 | cfg->process_cb = h->process_cb; 357 | cfg->param = h->param; 358 | 359 | http_begin_thread(_worker_accepter, cfg); 360 | 361 | return HTTP_TRUE; 362 | } 363 | 364 | void http_mpm_close(http_mpm_handle_t* p) 365 | { 366 | http_event_set(p->event_break_accepter); 367 | http_event_set(p->event_break_fastcgi); 368 | 369 | http_event_wait(p->event_accepter_exit); 370 | http_event_wait(p->event_fastcgi_exit); 371 | 372 | http_event_delete(p->event_break_accepter); 373 | http_event_delete(p->event_break_fastcgi); 374 | http_event_delete(p->event_accepter_exit); 375 | http_event_delete(p->event_fastcgi_exit); 376 | http_mutex_delete(p->mutex_fastcgi); 377 | http_event_delete(p->event_fire); 378 | http_event_delete(p->event_done); 379 | 380 | httpd_destroy(p->srv); 381 | 382 | http_free(p); 383 | } 384 | 385 | -------------------------------------------------------------------------------- /libhttpd/http_mpm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #ifndef HTTP_MPM_H_4DC53B00_A3A9_11E5_BA55_005056C00008_INCLUDED_ 27 | #define HTTP_MPM_H_4DC53B00_A3A9_11E5_BA55_005056C00008_INCLUDED_ 28 | 29 | //////////////////////////////////////////////////////////// 30 | typedef struct http_mpm_handle_t http_mpm_handle_t; 31 | 32 | typedef void (*http_mpm_initialize_cb)(void* param); 33 | typedef void (*http_mpm_finalize_cb)(void* param); 34 | typedef http_content_t* (*http_mpm_process_cb)(void* param, http_content_t* req); 35 | 36 | //////////////////////////////////////////////////////////// 37 | http_mpm_handle_t* http_mpm_create(char* ip, int port); 38 | 39 | void http_mpm_set_initialize( 40 | http_mpm_handle_t* h, 41 | http_mpm_initialize_cb cb, 42 | void* param); 43 | 44 | void http_mpm_set_finalize( 45 | http_mpm_handle_t* h, 46 | http_mpm_finalize_cb cb); 47 | 48 | void http_mpm_set_process( 49 | http_mpm_handle_t* h, 50 | http_mpm_process_cb cb); 51 | 52 | http_bool_t http_mpm_start(http_mpm_handle_t* h); 53 | 54 | void http_mpm_close(http_mpm_handle_t* h); 55 | 56 | #endif 57 | 58 | -------------------------------------------------------------------------------- /libhttpd/http_parse.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "http_common.h" 32 | #include "http_sys.h" 33 | #include "http_string.h" 34 | #include "http_map.h" 35 | 36 | #include "http_parse.h" 37 | 38 | typedef enum { 39 | _PARSE_REQUEST, 40 | _PARSE_RESPONSE 41 | }_http_prase_t; 42 | 43 | static http_bool_t _http_parse_request_line( 44 | const char* buf, 45 | int len, 46 | http_map_t* hdr); 47 | 48 | static http_bool_t _http_parse_response_line( 49 | const char* buf, 50 | int len, 51 | http_map_t* hdr); 52 | 53 | static http_bool_t _http_parse_header( 54 | const char* buf, 55 | int len, 56 | http_map_t* hdr); 57 | 58 | static http_bool_t _http_parse_lines( 59 | _http_prase_t type, 60 | const char* buffer, 61 | int buflen, 62 | http_map_t* hdr); 63 | 64 | http_bool_t _http_parse_request_line(const char* buf, int len, http_map_t* hdr) 65 | { 66 | const char* s; 67 | const char* pend; 68 | const char* p; 69 | char* v; 70 | 71 | pend = buf + len; 72 | 73 | //////////////////////////////////////////////////////// 74 | s = http_find_alpha(buf, len); 75 | if (s == NULL) { 76 | printf("ERROR:%s:%d\n", __FILE__, __LINE__); 77 | return HTTP_FALSE; 78 | } 79 | 80 | //////////////////////////////////////////////////////// 81 | //find 'method' end 82 | p = http_find_char(s, ' ', pend-s); 83 | if (p == NULL) { 84 | printf("ERROR:%s:%d\n", __FILE__, __LINE__); 85 | return HTTP_FALSE; 86 | } 87 | v = http_strndup(s, p-s); 88 | http_map_set(hdr, HTTP_METHOD, v); 89 | http_free(v); 90 | 91 | s = p+1; 92 | if (s >= pend) { 93 | printf("ERROR:%s:%d\n", __FILE__, __LINE__); 94 | return HTTP_FALSE; 95 | } 96 | 97 | //////////////////////////////////////////////////////// 98 | //find '/' 99 | p = http_find_char(s, '/', pend-s); 100 | if (p == NULL) { 101 | printf("ERROR:%s:%d\n", __FILE__, __LINE__); 102 | return HTTP_FALSE; 103 | } 104 | s = p; 105 | 106 | //find 'url' end 107 | p = http_find_char(s, ' ', pend-s); 108 | if (p == NULL) { 109 | printf("ERROR:%s:%d\n", __FILE__, __LINE__); 110 | return HTTP_FALSE; 111 | } 112 | v = http_strndup(s, p-s); 113 | http_map_set(hdr, HTTP_URL, v); 114 | http_free(v); 115 | 116 | s = p+1; 117 | if (s >= pend) { 118 | printf("ERROR:%s:%d\n", __FILE__, __LINE__); 119 | return HTTP_FALSE; 120 | } 121 | 122 | //////////////////////////////////////////////////////// 123 | //find 'HTTP/..' 124 | p = strstr(s, "HTTP/"); 125 | if (p == NULL) { 126 | printf("ERROR:%s:%d\n", __FILE__, __LINE__); 127 | return HTTP_FALSE; 128 | } 129 | 130 | //only accept 1.0 or 1.1 131 | if (strncmp(p, "HTTP/1.1", 8) == 0) { 132 | http_map_set(hdr, HTTP_VERSION, "HTTP/1.1"); 133 | 134 | } else if (strncmp(p, "HTTP/1.0", 8) == 0) { 135 | http_map_set(hdr, HTTP_VERSION, "HTTP/1.0"); 136 | 137 | } else { 138 | printf("ERROR:%s:%d\n", __FILE__, __LINE__); 139 | return HTTP_FALSE; 140 | } 141 | 142 | return HTTP_TRUE; 143 | } 144 | 145 | http_bool_t _http_parse_response_line(const char* buf, int len, http_map_t* hdr) 146 | { 147 | const char* s; 148 | const char* pend; 149 | const char* p; 150 | char* v; 151 | 152 | pend = buf + len; 153 | 154 | //////////////////////////////////////////////////////// 155 | s = http_find_alpha(buf, len); 156 | if (s == NULL) { 157 | printf("ERROR:%s:%d\n", __FILE__, __LINE__); 158 | return HTTP_FALSE; 159 | } 160 | 161 | //////////////////////////////////////////////////////// 162 | //find 'HTTP/..' 163 | p = strstr(s, "HTTP/"); 164 | if (p == NULL) { 165 | printf("ERROR:%s:%d\n", __FILE__, __LINE__); 166 | return HTTP_FALSE; 167 | } 168 | 169 | //only accept 1.0 or 1.1 170 | if (strncmp(p, "HTTP/1.1", 8) == 0) { 171 | http_map_set(hdr, HTTP_VERSION, "1.1"); 172 | 173 | } else if (strncmp(p, "HTTP/1.0", 8) == 0) { 174 | http_map_set(hdr, HTTP_VERSION, "1.0"); 175 | 176 | } else { 177 | printf("ERROR:%s:%d\n", __FILE__, __LINE__); 178 | return HTTP_FALSE; 179 | } 180 | s = p + 8; 181 | 182 | 183 | //////////////////////////////////////////////////////// 184 | //find 'digit' 185 | p = http_find_digit(s, pend-s); 186 | if (p == NULL) { 187 | printf("ERROR:%s:%d\n", __FILE__, __LINE__); 188 | return HTTP_FALSE; 189 | } 190 | s = p; 191 | 192 | p = http_find_char(s, ' ', pend-s); 193 | if (p == NULL) { 194 | printf("ERROR:%s:%d\n", __FILE__, __LINE__); 195 | return HTTP_FALSE; 196 | } 197 | 198 | v = http_strndup(s, p-s); 199 | http_map_set(hdr, HTTP_STATUS, v); 200 | http_free(v); 201 | 202 | s = p+1; 203 | if (s >= pend) { 204 | printf("ERROR:%s:%d\n", __FILE__, __LINE__); 205 | return HTTP_FALSE; 206 | } 207 | 208 | //////////////////////////////////////////////////////// 209 | //message 210 | v = http_strndup(s, pend-s); 211 | http_map_set(hdr, HTTP_MESSAGE, v); 212 | http_free(v); 213 | 214 | return HTTP_TRUE; 215 | } 216 | 217 | http_bool_t _http_parse_header(const char* buf, int len, http_map_t* hdr) 218 | { 219 | const char* s; 220 | const char* pend; 221 | const char* pcolon; 222 | const char* p; 223 | 224 | char* k = NULL; 225 | char* v = NULL; 226 | 227 | pend = buf + len; 228 | 229 | //////////////////////////////////////////////////////// 230 | s = http_find_alpha(buf, len); 231 | if (s == NULL) { 232 | return HTTP_FALSE; 233 | } 234 | 235 | pcolon = http_find_char(s, ':', pend-s); 236 | if (pcolon == NULL) { 237 | return HTTP_FALSE; 238 | } 239 | p = pcolon; 240 | while (p[-1] == ' ') { 241 | p--; 242 | } 243 | k = http_strndup(s, p-s); 244 | 245 | //////////////////////////////////////////////////////// 246 | s = http_find_nwhite(pcolon+1, pend-pcolon-1); 247 | if (s != NULL) { 248 | p = http_rfind_nwhite(s, pend-s); 249 | v = http_strndup(s, p+1-s); 250 | } 251 | 252 | http_map_set(hdr, k, v); 253 | http_free(k); 254 | if (v) { 255 | http_free(v); 256 | } 257 | 258 | return HTTP_TRUE; 259 | } 260 | 261 | http_bool_t _http_parse_lines( 262 | _http_prase_t type, 263 | const char* buffer, 264 | int buflen, 265 | http_map_t* hdr) 266 | { 267 | const char* p; 268 | const char* pend; 269 | const char* linebuf; 270 | int lineno; 271 | int len; 272 | int ret; 273 | 274 | lineno = 0; 275 | pend = buffer + buflen-1; 276 | linebuf = buffer; 277 | 278 | //walk through lines 279 | for (p = buffer;p < pend;p++) { 280 | if ((p[0] == '\r') && (p[1] == '\n')) { 281 | len = p - linebuf; 282 | if (len <= 0) {//CRLF 283 | break; 284 | } 285 | 286 | if (lineno == 0) { 287 | if (type == _PARSE_REQUEST) { 288 | ret = _http_parse_request_line(linebuf, len, hdr); 289 | } else { 290 | ret = _http_parse_response_line(linebuf, len, hdr); 291 | } 292 | } else { 293 | ret = _http_parse_header(linebuf, len, hdr); 294 | } 295 | 296 | if (!ret) { 297 | return HTTP_FALSE; 298 | } 299 | 300 | linebuf = p+2; 301 | lineno++; 302 | } 303 | } 304 | 305 | return HTTP_TRUE; 306 | } 307 | 308 | http_bool_t http_parse_request_headers(const char* buffer, int buflen, http_map_t* hdr) 309 | { 310 | return _http_parse_lines(_PARSE_REQUEST, buffer, buflen, hdr); 311 | } 312 | 313 | http_bool_t http_parse_response_headers(const char* buffer, int buflen, http_map_t* hdr) 314 | { 315 | return _http_parse_lines(_PARSE_RESPONSE, buffer, buflen, hdr); 316 | } 317 | 318 | -------------------------------------------------------------------------------- /libhttpd/http_parse.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #ifndef HTUTILS_PARSE_H_80B56DC0_8C0F_11E5_B6F5_005056C00008_INCLUDED_ 27 | #define HTUTILS_PARSE_H_80B56DC0_8C0F_11E5_B6F5_005056C00008_INCLUDED_ 28 | 29 | http_bool_t http_parse_request_headers( 30 | const char* buffer, 31 | int buflen, 32 | http_map_t* hdr); 33 | 34 | http_bool_t http_parse_response_headers( 35 | const char* buffer, 36 | int buflen, 37 | http_map_t* hdr); 38 | 39 | #endif 40 | 41 | -------------------------------------------------------------------------------- /libhttpd/http_sendrecv.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #ifndef HTTP_SENDRECV_H_BEDF370F_8F30_11E5_A650_005056C00008_INCLUDED_ 27 | #define HTTP_SENDRECV_H_BEDF370F_8F30_11E5_A650_005056C00008_INCLUDED_ 28 | 29 | const char* http_get_status_message(int status); 30 | 31 | int http_send_string(http_connection_t* conn, const char* s); 32 | int http_send_nl(http_connection_t* conn); 33 | int http_send_headers(http_connection_t* conn, http_map_t* hdr); 34 | int http_send_binary(http_connection_t* conn, char* buffer, int buflen); 35 | int http_send_file(http_connection_t* conn, const char* fn); 36 | 37 | int http_recv_headers(http_connection_t* conn, http_content_t* ct); 38 | int http_recv_binary(http_connection_t* conn, char* buffer, int expect_length); 39 | int http_recv_file(http_connection_t* conn, FILE* fp, int expect_length); 40 | int http_recv_body(http_connection_t* conn, http_content_t* ct); 41 | 42 | //this two function define in libhttp.c 43 | http_content_t* http_recv_request(http_connection_t* conn); 44 | http_content_t* http_recv_response(http_connection_t* conn); 45 | 46 | 47 | //@retval -1 error 48 | //@retval 0 ok 49 | //TODO:return http_bool_t 50 | int http_start_response(http_content_t* ct, int status); 51 | int http_start_request(http_content_t* ct, const char* method, const char* url); 52 | int http_header(http_content_t* ct, const char* key, const char* value); 53 | int http_write(http_content_t* ct, const char* buffer, int nr_bytes); 54 | int http_bind_file(http_content_t* ct, const char* fn); 55 | 56 | //@return number of bytes sent 57 | int http_send_response(http_connection_t* conn, http_content_t* ct); 58 | int http_send_request(http_connection_t* conn, http_content_t* ct); 59 | 60 | 61 | #endif 62 | 63 | -------------------------------------------------------------------------------- /libhttpd/http_server.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "libsocket.h" 32 | 33 | #include "http_common.h" 34 | #include "http_sys.h" 35 | #include "http_string.h" 36 | #include "http_connection.h" 37 | #include "http_server.h" 38 | 39 | httpd_server_t* httpd_create(const char* host, const char* ip, unsigned short port) 40 | { 41 | httpd_server_t* srv; 42 | socklen_t srv_len; 43 | int err; 44 | 45 | srv = (httpd_server_t*)http_malloc(sizeof(httpd_server_t)); 46 | if (host != NULL) { 47 | srv->host = http_strdup(host); 48 | } else if (ip != NULL) { 49 | srv->host = http_strdup(ip); 50 | } else { 51 | srv->host = http_strdup("0.0.0.0"); 52 | } 53 | srv->port = port; 54 | srv->handle = (socket_t*)http_malloc(sizeof(socket_t)); 55 | 56 | if (socket_create(srv->handle, AF_INET, SOCK_STREAM, IPPROTO_TCP) != IO_DONE) { 57 | http_free(srv->host); 58 | http_free(srv->handle); 59 | http_free(srv); 60 | return NULL; 61 | } 62 | 63 | if (ip == NULL) { 64 | srv->addr.sin_addr.s_addr = htons(INADDR_ANY); 65 | } else { 66 | srv->addr.sin_addr.s_addr = inet_addr(ip); 67 | } 68 | srv->addr.sin_family = AF_INET; 69 | srv->addr.sin_port = htons(port); 70 | srv_len = sizeof(srv->addr); 71 | 72 | err = socket_bind(srv->handle, (sockaddr*)&srv->addr, srv_len); 73 | if (err != IO_DONE) { 74 | printf("bind error = %d %s\n", err, socket_strerror(err)); 75 | socket_destroy(srv->handle); 76 | http_free(srv->host); 77 | http_free(srv->handle); 78 | http_free(srv); 79 | return NULL; 80 | } 81 | 82 | err = socket_listen(srv->handle, 1); 83 | if (err != IO_DONE) { 84 | printf("listen error = %d %s\n", err, socket_strerror(err)); 85 | socket_destroy(srv->handle); 86 | http_free(srv->host); 87 | http_free(srv->handle); 88 | http_free(srv); 89 | return NULL; 90 | } 91 | 92 | return srv; 93 | } 94 | 95 | void httpd_destroy(httpd_server_t* srv) 96 | { 97 | http_free(srv->host); 98 | socket_destroy(srv->handle); 99 | http_free(srv->handle); 100 | http_free(srv); 101 | } 102 | 103 | http_connection_t* httpd_accept(httpd_server_t* srv) 104 | { 105 | http_connection_t* conn; 106 | socklen_t cli_len; 107 | 108 | unsigned char* connected_ip; 109 | char remote_ip[16]; 110 | int err; 111 | 112 | conn = (http_connection_t*)http_malloc(sizeof(http_connection_t)); 113 | conn->host = NULL; 114 | conn->handle = (socket_t*)http_malloc(sizeof(socket_t)); 115 | 116 | cli_len = sizeof(conn->addr); 117 | err = socket_accept(srv->handle, conn->handle, 118 | (sockaddr*)&conn->addr, &cli_len, HTTP_ACCEPT_TIMEOUT); 119 | if (err != IO_DONE) { 120 | http_free(conn->host); 121 | http_free(conn->handle); 122 | http_free(conn); 123 | return NULL; 124 | } 125 | 126 | connected_ip = (unsigned char*)(&conn->addr.sin_addr.s_addr); 127 | sprintf(remote_ip, "%d.%d.%d.%d", 128 | connected_ip[0] & 0xFF, 129 | connected_ip[1] & 0xFF, 130 | connected_ip[2] & 0xFF, 131 | connected_ip[3] & 0xFF); 132 | conn->host = http_strdup(remote_ip); 133 | conn->port = ntohs(conn->addr.sin_port); 134 | 135 | return conn; 136 | } 137 | 138 | void httpd_close(http_connection_t* conn) 139 | { 140 | http_free(conn->host); 141 | socket_shutdown(conn->handle, SD_BOTH); 142 | socket_destroy(conn->handle); 143 | http_free(conn->handle); 144 | http_free(conn); 145 | } 146 | 147 | 148 | -------------------------------------------------------------------------------- /libhttpd/http_server.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #ifndef HTTP_SERVER_H_4D470970_5DD0_11E5_963F_005056C00008_INCLUDED_ 27 | #define HTTP_SERVER_H_4D470970_5DD0_11E5_963F_005056C00008_INCLUDED_ 28 | 29 | //////////////////////////////////////////////////////////// 30 | typedef struct _httpd_server_t { 31 | char* host; 32 | int port; 33 | socket_t* handle; 34 | struct sockaddr_in addr; 35 | }httpd_server_t; 36 | 37 | //////////////////////////////////////////////////////////// 38 | //@param host NULL or "www.example.com" 39 | //@param ip NULL or "127.0.0.1" 40 | httpd_server_t* httpd_create(const char* host, const char* ip, unsigned short port); 41 | void httpd_destroy(httpd_server_t* srv); 42 | 43 | http_connection_t* httpd_accept(httpd_server_t* srv); 44 | void httpd_close(http_connection_t* conn); 45 | 46 | #endif 47 | 48 | -------------------------------------------------------------------------------- /libhttpd/http_string.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include "http_common.h" 31 | #include "http_sys.h" 32 | #include "http_string.h" 33 | 34 | char* http_strdup(const char* s) 35 | { 36 | char* p; 37 | int n; 38 | 39 | n = strlen(s); 40 | 41 | p = (char*)http_malloc(n+1); 42 | memset(p, 0, n+1); 43 | if (n > 0) { 44 | memcpy(p, s, n); 45 | } 46 | 47 | return p; 48 | } 49 | 50 | char* http_strndup(const char* s, int n) 51 | { 52 | char* p; 53 | 54 | p = (char*)http_malloc(n+1); 55 | memset(p, 0, n+1); 56 | if (n > 0) { 57 | memcpy(p, s, n); 58 | } 59 | 60 | return p; 61 | } 62 | 63 | const char* http_find_char(const char* s, char ch, int len) 64 | { 65 | const char* pend; 66 | 67 | pend = s + len; 68 | 69 | while (s < pend) { 70 | if (*s == ch) { 71 | return s; 72 | } 73 | s++; 74 | } 75 | 76 | return NULL; 77 | } 78 | 79 | const char* http_rfind_char(const char* s, char ch, int len) 80 | { 81 | const char* p; 82 | 83 | p = s + len-1; 84 | 85 | while (s <= p) { 86 | if (*p == ch) { 87 | return p; 88 | } 89 | p--; 90 | } 91 | 92 | return NULL; 93 | } 94 | 95 | const char* http_find_alpha(const char* s, int len) 96 | { 97 | const char* p; 98 | const char* pend; 99 | 100 | p = s; 101 | pend = s + len; 102 | 103 | while (p < pend) { 104 | if (isalpha(*p)) { 105 | break; 106 | } 107 | p++; 108 | } 109 | if (p == pend) { 110 | return NULL; 111 | } 112 | 113 | return p; 114 | } 115 | 116 | const char* http_find_nwhite(const char* s, int len) 117 | { 118 | const char* p; 119 | const char* pend; 120 | 121 | p = s; 122 | pend = s + len; 123 | 124 | while (p < pend) { 125 | if (!isspace(*p)) { 126 | return p; 127 | } 128 | p++; 129 | } 130 | 131 | return NULL; 132 | } 133 | 134 | const char* http_rfind_nwhite(const char* s, int len) 135 | { 136 | const char* p; 137 | 138 | p = s + len -1; 139 | 140 | while (s <= p) { 141 | if (!isspace(*p)) { 142 | return p; 143 | } 144 | p--; 145 | } 146 | 147 | return NULL; 148 | } 149 | 150 | const char* http_find_crlf(const char* pbuf, int len) 151 | { 152 | while (len--) { 153 | if ((pbuf[0] == '\r') && 154 | (pbuf[1] == '\n') && 155 | (pbuf[2] == '\r') && 156 | (pbuf[3] == '\n')) 157 | { 158 | return (char*)pbuf; 159 | } 160 | 161 | pbuf++; 162 | } 163 | 164 | return NULL; 165 | } 166 | 167 | const char* http_find_digit(const char* s, int len) 168 | { 169 | const char* pend; 170 | 171 | pend = s + len; 172 | 173 | while (s < pend) { 174 | if (isdigit(*s)) { 175 | return s; 176 | } 177 | s++; 178 | } 179 | 180 | return NULL; 181 | } 182 | 183 | -------------------------------------------------------------------------------- /libhttpd/http_string.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #ifndef HTUTILS_STRING_H_7A9A725E_5DC9_11E5_80A3_005056C00008_INCLUDED_ 27 | #define HTUTILS_STRING_H_7A9A725E_5DC9_11E5_80A3_005056C00008_INCLUDED_ 28 | 29 | char* http_strdup(const char* s); 30 | char* http_strndup(const char* s, int n); 31 | 32 | const char* http_find_char(const char* s, char ch, int len); 33 | const char* http_rfind_char(const char* s, char ch, int len); 34 | 35 | const char* http_find_alpha(const char* s, int len); 36 | 37 | const char* http_find_nwhite(const char* s, int len); 38 | const char* http_rfind_nwhite(const char* s, int len); 39 | 40 | const char* http_find_crlf(const char* pbuf, int len); 41 | 42 | const char* http_find_digit(const char* s, int len); 43 | 44 | 45 | #endif 46 | 47 | -------------------------------------------------------------------------------- /libhttpd/http_sys.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #ifndef HTTP_SYS_H_2DD3B70F_8E6C_11E5_A502_005056C00008_INCLUDED_ 27 | #define HTTP_SYS_H_2DD3B70F_8E6C_11E5_A502_005056C00008_INCLUDED_ 28 | 29 | //////////////////////////////////////////////////////////// 30 | typedef enum { 31 | HTTP_FALSE = 0, 32 | HTTP_TRUE = 1 33 | }http_bool_t; 34 | 35 | void http_init(void); 36 | void http_fini(void); 37 | 38 | void http_msleep(int ms); 39 | 40 | 41 | //////////////////////////////////////////////////////////// 42 | int http_memory_usage(void); 43 | void http_memory_dump(void); 44 | 45 | #define http_malloc(size) http_malloc_((size), __FILE__, __LINE__) 46 | #define http_realloc(p, size) http_realloc_((p), (size), __FILE__, __LINE__) 47 | #define http_free(p) http_free_((p), __FILE__, __LINE__) 48 | 49 | void* http_malloc_(int size, char* file, int line); 50 | void* http_realloc_(void* p, int size, char* file, int line); 51 | void http_free_(void* p, char* file, int line); 52 | 53 | 54 | //////////////////////////////////////////////////////////// 55 | typedef struct http_sys_handle_t http_sys_handle_t; 56 | 57 | http_sys_handle_t* http_mutex_new(void); 58 | void http_mutex_delete(http_sys_handle_t* h); 59 | http_bool_t http_mutex_take(http_sys_handle_t* h); 60 | void http_mutex_give(http_sys_handle_t* h); 61 | 62 | http_sys_handle_t* http_event_new(void); 63 | void http_event_delete(http_sys_handle_t* h); 64 | http_bool_t http_event_trywait(http_sys_handle_t* h); 65 | http_bool_t http_event_wait(http_sys_handle_t* h); 66 | http_bool_t http_event_waittimeout(http_sys_handle_t* h, int tmo); 67 | void http_event_set(http_sys_handle_t* h); 68 | 69 | //////////////////////////////////////////////////////////// 70 | typedef void (http_thread_proc_t)(void* param); 71 | 72 | void http_begin_thread(http_thread_proc_t f, void* param); 73 | void http_end_thread(void); 74 | 75 | 76 | 77 | #endif 78 | 79 | -------------------------------------------------------------------------------- /libhttpd/http_sys_linux.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #ifndef TARGET_LINUX 32 | #error This file just support linux 33 | #endif 34 | 35 | #include 36 | #include 37 | #include 38 | #include "http_common.h" 39 | #include "http_sys.h" 40 | 41 | //////////////////////////////////////////////////////////// 42 | typedef struct _http_memory_t { 43 | void* p; 44 | int size; 45 | 46 | //reference to const string, don't modify! 47 | char* file; 48 | int line; 49 | }_http_memory_t; 50 | 51 | typedef enum { 52 | _HTTP_TYPE_MUTEX = 0, 53 | _HTTP_TYPE_EVENT = 1, 54 | }_http_handle_type_t; 55 | 56 | struct http_sys_handle_t 57 | { 58 | _http_handle_type_t type; 59 | pthread_mutex_t mutex; 60 | sem_t event; 61 | }; 62 | 63 | static _http_memory_t _memory_map[10 * 1024]; 64 | static const int _memory_len = sizeof(_memory_map)/sizeof(_memory_map[0]); 65 | static pthread_mutex_t _memory_mutex; 66 | 67 | //////////////////////////////////////////////////////////// 68 | void http_init(void) 69 | { 70 | memset(_memory_map, 0, sizeof(_memory_map)); 71 | pthread_mutex_init(&_memory_mutex, NULL); 72 | } 73 | 74 | void http_fini(void) 75 | { 76 | pthread_mutex_destroy(&_memory_mutex); 77 | } 78 | 79 | int http_memory_usage(void) 80 | { 81 | int i; 82 | int size = 0; 83 | 84 | if (pthread_mutex_lock(&_memory_mutex) != 0) { 85 | return -1; 86 | } 87 | 88 | for (i = 0;i < _memory_len;i++) { 89 | if (_memory_map[i].p == NULL) { 90 | continue; 91 | } 92 | size += _memory_map[i].size; 93 | } 94 | 95 | pthread_mutex_unlock(&_memory_mutex); 96 | 97 | return size; 98 | } 99 | 100 | void http_memory_dump(void) 101 | { 102 | int i; 103 | 104 | if (pthread_mutex_lock(&_memory_mutex) != 0) { 105 | return; 106 | } 107 | 108 | for (i = 0;i < _memory_len;i++) { 109 | if (_memory_map[i].p == NULL) { 110 | continue; 111 | } 112 | printf(" 0x%p: %8d bytes, %s:%d\n", 113 | _memory_map[i].p, 114 | _memory_map[i].size, 115 | _memory_map[i].file, 116 | _memory_map[i].line); 117 | } 118 | 119 | pthread_mutex_unlock(&_memory_mutex); 120 | } 121 | 122 | void* http_malloc_(int size, char* file, int line) 123 | { 124 | int i; 125 | void* p; 126 | 127 | if (pthread_mutex_lock(&_memory_mutex) != 0) { 128 | return NULL; 129 | } 130 | 131 | p = malloc(size); 132 | 133 | //add to memory map 134 | for (i = 0;i < _memory_len;i++) { 135 | if (_memory_map[i].p == NULL) { 136 | break; 137 | } 138 | } 139 | 140 | if (i == _memory_len) { 141 | printf("Error: memory map full!\n"); 142 | pthread_mutex_unlock(&_memory_mutex); 143 | exit(-1); 144 | } 145 | 146 | _memory_map[i].p = p; 147 | _memory_map[i].size = size; 148 | _memory_map[i].file = file; 149 | _memory_map[i].line = line; 150 | 151 | pthread_mutex_unlock(&_memory_mutex); 152 | 153 | return p; 154 | } 155 | 156 | void* http_realloc_(void* p, int size, char* file, int line) 157 | { 158 | int i; 159 | void* new_p; 160 | 161 | if (pthread_mutex_lock(&_memory_mutex) != 0) { 162 | return NULL; 163 | } 164 | 165 | for (i = 0;i < _memory_len;i++) { 166 | if (_memory_map[i].p == p) { 167 | break; 168 | } 169 | } 170 | 171 | if (i == _memory_len) { 172 | printf("Error: realloc %p not exist in memory map!\n", p); 173 | printf(" from %s:%d\n", file, line); 174 | pthread_mutex_unlock(&_memory_mutex); 175 | exit(-1); 176 | } 177 | 178 | new_p = realloc(p, size); 179 | _memory_map[i].p = new_p; 180 | _memory_map[i].size = size; 181 | _memory_map[i].file = file; 182 | _memory_map[i].line = line; 183 | pthread_mutex_unlock(&_memory_mutex); 184 | 185 | return new_p; 186 | } 187 | 188 | void http_free_(void* p, char* file, int line) 189 | { 190 | int i; 191 | 192 | if (p == NULL) { 193 | return; 194 | } 195 | 196 | if (pthread_mutex_lock(&_memory_mutex) != 0) { 197 | return; 198 | } 199 | 200 | for (i = 0;i < _memory_len;i++) { 201 | if (_memory_map[i].p == p) { 202 | break; 203 | } 204 | } 205 | 206 | if (i == _memory_len) { 207 | printf("Error: free %p not exist in memory map!\n", p); 208 | printf(" from %s:%d\n", file, line); 209 | exit(-1); 210 | } 211 | 212 | _memory_map[i].p = NULL; 213 | _memory_map[i].size = 0; 214 | 215 | free(p); 216 | 217 | pthread_mutex_unlock(&_memory_mutex); 218 | } 219 | 220 | http_sys_handle_t* http_mutex_new(void) 221 | { 222 | http_sys_handle_t* h; 223 | 224 | h = (http_sys_handle_t*)http_malloc(sizeof(http_sys_handle_t)); 225 | h->type = _HTTP_TYPE_MUTEX; 226 | pthread_mutex_init(&h->mutex, NULL); 227 | 228 | return h; 229 | } 230 | 231 | void http_mutex_delete(http_sys_handle_t* h) 232 | { 233 | if ((h == NULL) || (h->type != _HTTP_TYPE_MUTEX)) { 234 | return; 235 | } 236 | 237 | pthread_mutex_destroy(&h->mutex); 238 | 239 | http_free(h); 240 | } 241 | 242 | http_bool_t http_mutex_take(http_sys_handle_t* h) 243 | { 244 | if ((h == NULL) || (h->type != _HTTP_TYPE_MUTEX)) { 245 | return HTTP_FALSE; 246 | } 247 | 248 | if (pthread_mutex_lock(&h->mutex) != 0) { 249 | return HTTP_FALSE; 250 | } 251 | return HTTP_TRUE; 252 | } 253 | 254 | void http_mutex_give(http_sys_handle_t* h) 255 | { 256 | if ((h == NULL) || (h->type != _HTTP_TYPE_MUTEX)) { 257 | return; 258 | } 259 | pthread_mutex_unlock(&h->mutex); 260 | } 261 | 262 | http_sys_handle_t* http_event_new(void) 263 | { 264 | http_sys_handle_t* h; 265 | 266 | h = (http_sys_handle_t*)http_malloc(sizeof(http_sys_handle_t)); 267 | h->type = _HTTP_TYPE_EVENT; 268 | sem_init(&h->event, 0, 0); 269 | 270 | return h; 271 | } 272 | 273 | void http_event_delete(http_sys_handle_t* h) 274 | { 275 | if ((h == NULL) || (h->type != _HTTP_TYPE_EVENT)) { 276 | return; 277 | } 278 | 279 | sem_destroy(&h->event); 280 | 281 | http_free(h); 282 | } 283 | 284 | http_bool_t http_event_trywait(http_sys_handle_t* h) 285 | { 286 | if ((h == NULL) || (h->type != _HTTP_TYPE_EVENT)) { 287 | return HTTP_FALSE; 288 | } 289 | 290 | if (sem_trywait(&h->event) != 0) { 291 | return HTTP_FALSE; 292 | } 293 | 294 | return HTTP_TRUE; 295 | } 296 | 297 | http_bool_t http_event_wait(http_sys_handle_t* h) 298 | { 299 | if ((h == NULL) || (h->type != _HTTP_TYPE_EVENT)) { 300 | return HTTP_FALSE; 301 | } 302 | 303 | if (sem_wait(&h->event) != 0) { 304 | return HTTP_FALSE; 305 | } 306 | 307 | return HTTP_TRUE; 308 | } 309 | 310 | http_bool_t http_event_waittimeout(http_sys_handle_t* h, int tmo) 311 | { 312 | struct timespec t; 313 | long ovf_sec; 314 | long tv_nsec; 315 | 316 | if ((h == NULL) || (h->type != _HTTP_TYPE_EVENT)) { 317 | return HTTP_FALSE; 318 | } 319 | 320 | if (clock_gettime(CLOCK_REALTIME, &t) != 0) { 321 | printf("clock_gettime error\n"); 322 | } 323 | 324 | tv_nsec = t.tv_nsec + (tmo % 1000) * 1000 * 1000; 325 | ovf_sec = tv_nsec/1000/1000/1000; 326 | if (ovf_sec > 0) { 327 | t.tv_sec++; 328 | tv_nsec = tv_nsec - ovf_sec*1000*1000*1000; 329 | } 330 | t.tv_sec += tmo / 1000; 331 | t.tv_nsec = tv_nsec; 332 | 333 | if (sem_timedwait(&h->event, &t) != 0) { 334 | return HTTP_FALSE; 335 | } 336 | return HTTP_TRUE; 337 | } 338 | 339 | void http_event_set(http_sys_handle_t* h) 340 | { 341 | if ((h == NULL) || (h->type != _HTTP_TYPE_EVENT)) { 342 | return; 343 | } 344 | sem_post(&h->event); 345 | } 346 | 347 | void http_msleep(int ms) 348 | { 349 | usleep(ms * 1000); 350 | } 351 | 352 | typedef void* (*_pthread_callback_t)(void*); 353 | 354 | void http_begin_thread(http_thread_proc_t f, void* param) 355 | { 356 | pthread_t tid; 357 | int ret; 358 | 359 | ret = pthread_create(&tid, NULL, (_pthread_callback_t)f, param); 360 | if (ret != 0) { 361 | if (ret == EAGAIN) { 362 | printf("pthread_create: the system lacked the necessary resources!\n"); 363 | } else { 364 | printf("pthread_create return %d\n", ret); 365 | } 366 | } 367 | pthread_detach(tid); 368 | } 369 | 370 | void http_end_thread(void) 371 | { 372 | pthread_exit(NULL); 373 | } 374 | 375 | -------------------------------------------------------------------------------- /libhttpd/http_sys_w32.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #ifndef TARGET_WINDOWS 31 | #error This file just support windows 32 | #endif 33 | 34 | #include 35 | #include 36 | #include "http_common.h" 37 | #include "http_sys.h" 38 | 39 | //////////////////////////////////////////////////////////// 40 | typedef struct _http_memory_t { 41 | //remember pointer and size 42 | void* p; 43 | int size; 44 | 45 | //reference to const string, don't modify! 46 | char* file; 47 | int line; 48 | }_http_memory_t; 49 | 50 | typedef enum { 51 | _HTTP_TYPE_MUTEX = 0, 52 | _HTTP_TYPE_EVENT = 1, 53 | }_http_handle_type_t; 54 | 55 | typedef struct http_sys_handle_t 56 | { 57 | _http_handle_type_t type; 58 | HANDLE mutex; 59 | HANDLE event; 60 | }http_sys_handle_t; 61 | 62 | //this for memory alloc and free 63 | //because http server running in multithread mode, 64 | //so memory must lock before any modify! 65 | // 66 | //this record memory pointer for leak checking 67 | static _http_memory_t _memory_map[10 * 1024]; 68 | static const int _memory_len = sizeof(_memory_map)/sizeof(_memory_map[0]); 69 | static HANDLE _memory_mutex = INVALID_HANDLE_VALUE; 70 | 71 | //////////////////////////////////////////////////////////// 72 | void http_init(void) 73 | { 74 | memset(_memory_map, 0, sizeof(_memory_map)); 75 | _memory_mutex = CreateMutex(NULL, FALSE, NULL); 76 | } 77 | 78 | void http_fini(void) 79 | { 80 | if (_memory_mutex != INVALID_HANDLE_VALUE) { 81 | CloseHandle(_memory_mutex); 82 | _memory_mutex = INVALID_HANDLE_VALUE; 83 | } 84 | } 85 | 86 | int http_memory_usage(void) 87 | { 88 | int i; 89 | int size = 0; 90 | 91 | if (WaitForSingleObject(_memory_mutex, INFINITE) != WAIT_OBJECT_0) { 92 | return -1; 93 | } 94 | 95 | for (i = 0;i < _memory_len;i++) { 96 | if (_memory_map[i].p == NULL) { 97 | continue; 98 | } 99 | size += _memory_map[i].size; 100 | } 101 | 102 | ReleaseMutex(_memory_mutex); 103 | 104 | return size; 105 | } 106 | 107 | void http_memory_dump(void) 108 | { 109 | int i; 110 | 111 | if (WaitForSingleObject(_memory_mutex, INFINITE) != WAIT_OBJECT_0) { 112 | return; 113 | } 114 | 115 | for (i = 0;i < _memory_len;i++) { 116 | if (_memory_map[i].p == NULL) { 117 | continue; 118 | } 119 | printf(" 0x%p: %8d bytes, %s:%d\n", 120 | _memory_map[i].p, 121 | _memory_map[i].size, 122 | _memory_map[i].file, 123 | _memory_map[i].line); 124 | } 125 | 126 | ReleaseMutex(_memory_mutex); 127 | } 128 | 129 | void* http_malloc_(int size, char* file, int line) 130 | { 131 | int i; 132 | void* p; 133 | 134 | if (WaitForSingleObject(_memory_mutex, INFINITE) != WAIT_OBJECT_0) { 135 | printf("ERROR %s:%d\n", __FILE__, __LINE__); 136 | return NULL; 137 | } 138 | 139 | p = malloc(size); 140 | 141 | //add to memory map 142 | for (i = 0;i < _memory_len;i++) { 143 | if (_memory_map[i].p == NULL) { 144 | break; 145 | } 146 | } 147 | 148 | if (i == _memory_len) { 149 | printf("ERROR %s:%d\n", __FILE__, __LINE__); 150 | ReleaseMutex(_memory_mutex); 151 | exit(-1); 152 | } 153 | 154 | _memory_map[i].p = p; 155 | _memory_map[i].size = size; 156 | _memory_map[i].file = file; 157 | _memory_map[i].line = line; 158 | 159 | ReleaseMutex(_memory_mutex); 160 | 161 | return p; 162 | } 163 | 164 | void* http_realloc_(void* p, int size, char* file, int line) 165 | { 166 | int i; 167 | void* new_p; 168 | 169 | if (WaitForSingleObject(_memory_mutex, INFINITE) != WAIT_OBJECT_0) { 170 | printf("ERROR %s:%d\n", __FILE__, __LINE__); 171 | return NULL; 172 | } 173 | 174 | for (i = 0;i < _memory_len;i++) { 175 | if (_memory_map[i].p == p) { 176 | break; 177 | } 178 | } 179 | 180 | if (i == _memory_len) { 181 | printf("ERROR %s:%d\n", __FILE__, __LINE__); 182 | ReleaseMutex(_memory_mutex); 183 | exit(-1); 184 | } 185 | 186 | new_p = realloc(p, size); 187 | _memory_map[i].p = new_p; 188 | _memory_map[i].size = size; 189 | _memory_map[i].file = file; 190 | _memory_map[i].line = line; 191 | 192 | ReleaseMutex(_memory_mutex); 193 | 194 | return new_p; 195 | } 196 | 197 | void http_free_(void* p, char* file, int line) 198 | { 199 | int i; 200 | 201 | if (p == NULL) { 202 | return; 203 | } 204 | 205 | if (WaitForSingleObject(_memory_mutex, INFINITE) != WAIT_OBJECT_0) { 206 | printf("ERROR %s:%d\n", __FILE__, __LINE__); 207 | return; 208 | } 209 | 210 | for (i = 0;i < _memory_len;i++) { 211 | if (_memory_map[i].p == p) { 212 | break; 213 | } 214 | } 215 | 216 | if (i == _memory_len) { 217 | printf("ERROR %s:%d\n", __FILE__, __LINE__); 218 | ReleaseMutex(_memory_mutex); 219 | exit(-1); 220 | } 221 | 222 | _memory_map[i].p = NULL; 223 | _memory_map[i].size = 0; 224 | 225 | free(p); 226 | 227 | ReleaseMutex(_memory_mutex); 228 | } 229 | 230 | http_sys_handle_t* http_mutex_new(void) 231 | { 232 | http_sys_handle_t* h; 233 | 234 | h = (http_sys_handle_t*)http_malloc(sizeof(http_sys_handle_t)); 235 | h->type = _HTTP_TYPE_MUTEX; 236 | h->mutex= CreateMutex(NULL, FALSE, NULL); 237 | 238 | return h; 239 | } 240 | 241 | void http_mutex_delete(http_sys_handle_t* h) 242 | { 243 | if ((h == NULL) || (h->type != _HTTP_TYPE_MUTEX)) { 244 | return; 245 | } 246 | 247 | CloseHandle(h->mutex); 248 | h->mutex = INVALID_HANDLE_VALUE; 249 | 250 | http_free(h); 251 | } 252 | 253 | http_bool_t http_mutex_take(http_sys_handle_t* h) 254 | { 255 | if ((h == NULL) || (h->type != _HTTP_TYPE_MUTEX)) { 256 | return HTTP_FALSE; 257 | } 258 | 259 | if (WaitForSingleObject(h->mutex, INFINITE) != WAIT_OBJECT_0) { 260 | return HTTP_FALSE; 261 | } 262 | return HTTP_TRUE; 263 | } 264 | 265 | void http_mutex_give(http_sys_handle_t* h) 266 | { 267 | if ((h == NULL) || (h->type != _HTTP_TYPE_MUTEX)) { 268 | return; 269 | } 270 | ReleaseMutex(h->mutex); 271 | } 272 | 273 | http_sys_handle_t* http_event_new(void) 274 | { 275 | http_sys_handle_t* h; 276 | 277 | h = (http_sys_handle_t*)http_malloc(sizeof(http_sys_handle_t)); 278 | h->type = _HTTP_TYPE_EVENT; 279 | h->event= CreateEvent(NULL, FALSE, FALSE, NULL); 280 | 281 | return h; 282 | } 283 | 284 | void http_event_delete(http_sys_handle_t* h) 285 | { 286 | if ((h == NULL) || (h->type != _HTTP_TYPE_EVENT)) { 287 | return; 288 | } 289 | 290 | CloseHandle(h->event); 291 | h->event = INVALID_HANDLE_VALUE; 292 | 293 | http_free(h); 294 | } 295 | 296 | http_bool_t http_event_trywait(http_sys_handle_t* h) 297 | { 298 | if ((h == NULL) || (h->type != _HTTP_TYPE_EVENT)) { 299 | return HTTP_FALSE; 300 | } 301 | 302 | if (WaitForSingleObject(h->event, 0) != WAIT_OBJECT_0) { 303 | return HTTP_FALSE; 304 | } 305 | return HTTP_TRUE; 306 | } 307 | 308 | http_bool_t http_event_wait(http_sys_handle_t* h) 309 | { 310 | if ((h == NULL) || (h->type != _HTTP_TYPE_EVENT)) { 311 | return HTTP_FALSE; 312 | } 313 | 314 | if (WaitForSingleObject(h->event, INFINITE) != WAIT_OBJECT_0) { 315 | return HTTP_FALSE; 316 | } 317 | return HTTP_TRUE; 318 | } 319 | 320 | http_bool_t http_event_waittimeout(http_sys_handle_t* h, int tmo) 321 | { 322 | if ((h == NULL) || (h->type != _HTTP_TYPE_EVENT)) { 323 | return HTTP_FALSE; 324 | } 325 | 326 | if (WaitForSingleObject(h->event, tmo) != WAIT_OBJECT_0) { 327 | return HTTP_FALSE; 328 | } 329 | return HTTP_TRUE; 330 | } 331 | 332 | void http_event_set(http_sys_handle_t* h) 333 | { 334 | if ((h == NULL) || (h->type != _HTTP_TYPE_EVENT)) { 335 | return; 336 | } 337 | SetEvent(h->event); 338 | } 339 | 340 | void http_msleep(int ms) 341 | { 342 | Sleep(ms); 343 | } 344 | 345 | void http_begin_thread(http_thread_proc_t f, void* param) 346 | { 347 | _beginthread(f, 0, param); 348 | } 349 | 350 | void http_end_thread(void) 351 | { 352 | _endthread(); 353 | } 354 | 355 | -------------------------------------------------------------------------------- /libhttpd/http_urldecode.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "http_common.h" 32 | #include "http_sys.h" 33 | #include "http_string.h" 34 | #include "http_map.h" 35 | 36 | static int _parse_hex(const char* s, int len); 37 | 38 | 39 | int _parse_hex(const char* s, int len) 40 | { 41 | int v = 0; 42 | char c; 43 | 44 | while (len-- > 0) { 45 | c = tolower(*s++); 46 | if (('0' <= c) && (c <= '9')) { 47 | c = c - '0'; 48 | } else if (('a' <= c) && (c <= 'f')) { 49 | c = c - 'a' + 10; 50 | } else { 51 | return 0; 52 | } 53 | 54 | v = v * 16 + c; 55 | } 56 | 57 | return v; 58 | } 59 | 60 | int http_unquote(const char* buffer, int len, char** pbufout) 61 | { 62 | const char* pend; 63 | const char* p; 64 | char* bufout; 65 | char* pwrite; 66 | char c; 67 | 68 | bufout = http_malloc(sizeof(char*) * len + 1);; 69 | pwrite = bufout; 70 | p = buffer; 71 | pend = buffer + len; 72 | 73 | while (p < pend) { 74 | if (*p == '+') { 75 | *pwrite++ = ' '; 76 | p++; 77 | 78 | } else if (*p == '%') { 79 | if (pend - p <= 2) { 80 | printf("ERROR\n"); 81 | return -1; 82 | } 83 | c = _parse_hex(p+1, 2); 84 | *pwrite++ = c; 85 | p = p + 3; 86 | 87 | } else { 88 | *pwrite++ = *p++; 89 | } 90 | } 91 | *pwrite++ = '\0'; 92 | 93 | if (pbufout != NULL) { 94 | *pbufout = bufout; 95 | } else { 96 | http_free(bufout); 97 | } 98 | 99 | return pwrite - bufout; 100 | } 101 | 102 | http_map_t* http_urldecode(char* buffer, int len) 103 | { 104 | http_map_t* m; 105 | 106 | char* pend; 107 | char* s; 108 | char* p; 109 | 110 | char* key = NULL; 111 | char* value = NULL; 112 | 113 | pend = buffer + len; 114 | s = buffer; 115 | p = buffer; 116 | 117 | m = http_map_new(HTTP_DEFAULT_HEADERS_COUNT); 118 | 119 | while (p < pend) { 120 | if (*p == '=') { 121 | if (key != NULL) { 122 | http_map_set(m, key, ""); 123 | http_free(key); 124 | key = NULL; 125 | } 126 | http_unquote(s, p-s, &key); 127 | s = ++p; 128 | 129 | } else if (*p == '&') { 130 | if (s < p) { 131 | if (key) { 132 | http_unquote(s, p-s, &value); 133 | http_map_set(m, key, value); 134 | } else { 135 | http_unquote(s, p-s, &key); 136 | http_map_set(m, key, ""); 137 | } 138 | 139 | } else if (key != NULL) { 140 | http_map_set(m, key, ""); 141 | } 142 | 143 | if (key) { 144 | http_free(key); 145 | key = NULL; 146 | } 147 | if (value) { 148 | http_free(value); 149 | value = NULL; 150 | } 151 | 152 | s = ++p; 153 | 154 | } else { 155 | p++; 156 | } 157 | } 158 | 159 | if (s < p) { 160 | if (key) { 161 | http_unquote(s, p-s, &value); 162 | http_map_set(m, key, value); 163 | } else { 164 | http_unquote(s, p-s, &key); 165 | http_map_set(m, key, ""); 166 | } 167 | 168 | } else if (key != NULL) { 169 | http_map_set(m, key, ""); 170 | } 171 | 172 | //cleanup 173 | if (key) { 174 | http_free(key); 175 | key = NULL; 176 | } 177 | if (value) { 178 | http_free(value); 179 | value = NULL; 180 | } 181 | 182 | return m; 183 | } 184 | 185 | 186 | -------------------------------------------------------------------------------- /libhttpd/http_urldecode.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #ifndef HTTP_URLDECODE_H_3CDC8961_9D87_11E5_A40D_005056C00008_INCLUDED_ 27 | #define HTTP_URLDECODE_H_3CDC8961_9D87_11E5_A40D_005056C00008_INCLUDED_ 28 | 29 | int http_unquote(const char* buffer, int len, char** pbufout); 30 | http_map_t* http_urldecode(char* buffer, int len); 31 | 32 | #endif 33 | 34 | -------------------------------------------------------------------------------- /libhttpd/http_urlencode.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "http_common.h" 32 | #include "http_sys.h" 33 | #include "http_string.h" 34 | #include "http_map.h" 35 | 36 | static char always_safe_buf[] = 37 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 38 | "abcdefghijklmnopqrstuvwxyz" 39 | "0123456789_.-"; 40 | static int always_safe_len = sizeof(always_safe_buf)/sizeof(always_safe_buf[0]) - 1; 41 | 42 | 43 | static char _to_hex(char c); 44 | 45 | 46 | //quote('abc def') -> 'abc%20def' 47 | // 48 | // Each part of a URL, e.g. the path info, the query, etc., has a 49 | // different set of reserved characters that must be quoted. 50 | // 51 | // RFC 2396 Uniform Resource Identifiers (URI): Generic Syntax lists 52 | // the following reserved characters. 53 | // 54 | // reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | 55 | // "$" | "," 56 | // 57 | // Each of these characters is reserved in some component of a URL, 58 | // but not necessarily in all of them. 59 | // 60 | // By default, the quote function is intended for quoting the path 61 | // section of a URL. Thus, it will not encode '/'. This character 62 | // is reserved, but in typical usage the quote function is being 63 | // called on a path where the existing slash characters are used as 64 | // reserved characters. 65 | // 66 | //static char safe_chars_buf[] = "%/:=&?~#+!$,;'@()*[]|"; 67 | //static int safe_chars_len = sizeof(safe_chars_buf)/sizeof(safe_chars_buf[0]) - 1; 68 | 69 | char _to_hex(char c) 70 | { 71 | if ((0 <= c) && (c <= 9)) { 72 | return c + '0'; 73 | } else { 74 | return c - 10 + 'A'; 75 | } 76 | } 77 | 78 | //@retval strlen(*pbufout) + 1; 79 | int http_quote(const char* buffer, int len, char** pbufout) 80 | { 81 | const char* p; 82 | const char* pend; 83 | char* bufout; 84 | char* pwrite; 85 | int i; 86 | char c; 87 | 88 | bufout = (char*)http_malloc(sizeof(char) * 3 * len + 1); 89 | pend = buffer + len; 90 | p = buffer; 91 | pwrite = bufout; 92 | 93 | while (p < pend) { 94 | c = *p++; 95 | for (i = 0;i < always_safe_len;i++) { 96 | if (c == always_safe_buf[i]) { 97 | break; 98 | } 99 | } 100 | 101 | if (i != always_safe_len) { 102 | *pwrite++ = c; 103 | } else { 104 | *pwrite++ = '%'; 105 | *pwrite++ = _to_hex(c >> 4); 106 | *pwrite++ = _to_hex(c & 0x0Fu); 107 | } 108 | } 109 | *pwrite++ = '\0'; 110 | 111 | if (pbufout != NULL) { 112 | *pbufout = bufout; 113 | } else { 114 | http_free(bufout); 115 | } 116 | 117 | return pwrite - bufout; 118 | } 119 | 120 | int http_urlencode(http_map_t* m, char** pout) 121 | { 122 | http_map_iter_t iter; 123 | int len; 124 | char* k; 125 | char* v; 126 | char* encoded_buf; 127 | int encoded_maxsize; 128 | int encoded_size; 129 | 130 | if (pout == NULL) { 131 | return -1; 132 | } 133 | 134 | encoded_maxsize = 1000; 135 | encoded_size = 0; 136 | encoded_buf = (char*)http_malloc(encoded_maxsize); 137 | 138 | for (http_map_begin(m, &iter);http_map_valid(&iter);http_map_next(&iter)) { 139 | //process key 140 | if ((iter.k == NULL) || (iter.k[0] == '\0')) { 141 | continue; 142 | } 143 | len = http_quote(iter.k, strlen(iter.k), &k); 144 | if (encoded_size + len >= encoded_maxsize) { 145 | encoded_maxsize *= 2; 146 | encoded_buf = (char*)http_realloc(encoded_buf, encoded_maxsize); 147 | } 148 | memcpy(encoded_buf + encoded_size, k, len);//len included '\0' 149 | encoded_size += len - 1; 150 | encoded_buf[encoded_size++] = '='; 151 | encoded_buf[encoded_size] = '\0'; 152 | http_free(k); 153 | 154 | //process value 155 | if ((iter.v == NULL) || (iter.v[0] == '\0')) { 156 | continue; 157 | } 158 | len = http_quote(iter.v, strlen(iter.v), &v); 159 | if (encoded_size + len >= encoded_maxsize) { 160 | encoded_maxsize *= 2; 161 | encoded_buf = (char*)http_realloc(encoded_buf, encoded_maxsize); 162 | } 163 | memcpy(encoded_buf + encoded_size, v, len);//len included '\0' 164 | encoded_size += len - 1; 165 | encoded_buf[encoded_size++] = '&'; 166 | encoded_buf[encoded_size] = '\0'; 167 | http_free(k); 168 | } 169 | 170 | *pout = encoded_buf; 171 | 172 | return encoded_size; 173 | } 174 | 175 | -------------------------------------------------------------------------------- /libhttpd/http_urlencode.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #ifndef HTTP_URLENCODE_H_349676CF_9D87_11E5_9E45_005056C00008_INCLUDED_ 27 | #define HTTP_URLENCODE_H_349676CF_9D87_11E5_9E45_005056C00008_INCLUDED_ 28 | 29 | int http_quote(const char* buffer, int len, char** pbufout); 30 | int http_urlencode(http_map_t* m, char** pout); 31 | 32 | #endif 33 | 34 | -------------------------------------------------------------------------------- /libhttpd/libhttp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include "libhttp.h" 31 | 32 | const char HTTP_BUILD_VERSION[] = 33 | HTTP_DEFAULT_SERVER 34 | " " 35 | __DATE__ 36 | " " 37 | __TIME__; 38 | 39 | -------------------------------------------------------------------------------- /libhttpd/libhttp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #ifndef LIBHTTP_H_46B44FD1_97F2_11E5_AEBE_005056C00008_INCLUDED_ 27 | #define LIBHTTP_H_46B44FD1_97F2_11E5_AEBE_005056C00008_INCLUDED_ 28 | 29 | #include "libsocket.h" 30 | 31 | #include "http_common.h" 32 | #include "http_sys.h" 33 | #include "http_string.h" 34 | #include "http_map.h" 35 | #include "http_buffer.h" 36 | #include "http_content.h" 37 | 38 | #include "http_connection.h" 39 | #include "http_client.h" 40 | #include "http_server.h" 41 | #include "http_sendrecv.h" 42 | #include "http_parse.h" 43 | 44 | #include "http_urlencode.h" 45 | #include "http_urldecode.h" 46 | 47 | #include "http_mpm.h" 48 | 49 | extern const char HTTP_BUILD_VERSION[]; 50 | 51 | http_content_t* http_recv_request(http_connection_t* conn); 52 | http_content_t* http_recv_response(http_connection_t* conn); 53 | 54 | #endif 55 | 56 | -------------------------------------------------------------------------------- /libhttpd/wsgi.txt: -------------------------------------------------------------------------------- 1 | { 2 | 'HTTP_COOKIE': '.....', 3 | 'HTTP_USER_AGENT': 'Mozilla/5.0 ...', 4 | 'HTTP_CONNECTION': 'keep-alive', 5 | 'HTTP_HOST': '127.0.0.1:1000', 6 | 'HTTP_ACCEPT': 'text/html', 7 | 'HTTP_ACCEPT_LANGUAGE': 'en', 8 | 'HTTP_ACCEPT_ENCODING': 'gzip, deflate, sdch' 9 | 'CONTENT_LENGTH': '', 10 | 'CONTENT_TYPE': '', 11 | 'PATH_INFO': '/index', 12 | 'QUERY_STRING': '', 13 | 'REMOTE_PORT': 12234, 14 | 'REQUEST_METHOD': 'GET', 15 | 'REMOTE_ADDR': '127.0.0.1', 16 | 'SERVER_SOFTWARE': '...', 17 | 'SCRIPT_NAME': '', 18 | 'SERVER_PROTOCOL': 'HTTP/1.1', 19 | 'SERVER_NAME': '127.0.0.1', 20 | 'SERVER_PORT': '1000', 21 | 'wsgi.multiprocess': False, 22 | 'wsgi.url_scheme': 'http', 23 | 'wsgi.input': , 24 | 'wsgi.multithread': False, 25 | 'wsgi.version': (1, 0), 26 | 'wsgi.run_once': False, 27 | 'wsgi.errors': ', mode 'w' at ......>, 28 | } 29 | 30 | 31 | -------------------------------------------------------------------------------- /libhttpd/wsgi_server.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #ifndef WSGI_SERVER_H_61A9B6B0_AAAB_11E5_93C6_005056C00008_INCLUDED_ 27 | #define WSGI_SERVER_H_61A9B6B0_AAAB_11E5_93C6_005056C00008_INCLUDED_ 28 | 29 | #define VARNAME_FILE "__file__" 30 | #define VARNAME_STATUS "__http_response_status__" 31 | #define VARNAME_HEADERS "__http_response_headers__" 32 | 33 | 34 | typedef struct wsgi_chain_t wsgi_chain_t; 35 | typedef struct wsgi_handle_t wsgi_handle_t; 36 | typedef void (*wsgi_cb_t)(wsgi_handle_t* srv, void* param); 37 | 38 | struct wsgi_chain_t { 39 | wsgi_cb_t cb; 40 | void* param; 41 | }; 42 | 43 | struct wsgi_handle_t { 44 | http_mpm_handle_t* mpm; 45 | duk_context* ctx; 46 | int argc; 47 | char** argv; 48 | int nr_init; 49 | int nr_fini; 50 | wsgi_chain_t* init_chain; 51 | wsgi_chain_t* fini_chain; 52 | }; 53 | 54 | wsgi_handle_t* wsgi_create(char* ip, int port); 55 | int wsgi_start(wsgi_handle_t* h, int argc, char* argv[], char* env[]); 56 | void wsgi_close(wsgi_handle_t* h); 57 | 58 | void wsgi_add_initialize_chain(wsgi_handle_t* h, wsgi_cb_t cb, void* param); 59 | void wsgi_add_finalize_chain(wsgi_handle_t* h, wsgi_cb_t cb, void* param); 60 | 61 | #endif 62 | 63 | -------------------------------------------------------------------------------- /libsocket/libsocket.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | * 25 | * this code copy and modify from luasocket, which license is MIT:) 26 | * @ref luasocket/libsocket.h 27 | * @ref luasocket/usocket.c 28 | * @ref luasocket/wsocket.c 29 | * 30 | * 31 | * LuaSocket 2.0.2 license 32 | * Copyright ?2004-2007 Diego Nehab 33 | * 34 | * Permission is hereby granted, free of charge, to any person obtaining a 35 | * copy of this software and associated documentation files (the "Software"), 36 | * to deal in the Software without restriction, including without limitation 37 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 38 | * and/or sell copies of the Software, and to permit persons to whom the 39 | * Software is furnished to do so, subject to the following conditions: 40 | * 41 | * The above copyright notice and this permission notice shall be included in 42 | * all copies or substantial portions of the Software. 43 | * 44 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 45 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 46 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 47 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 48 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 49 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 50 | * DEALINGS IN THE SOFTWARE. 51 | */ 52 | 53 | #ifndef LIBSOCKET_H_53FF16DE_4A25_11E5_917E_005056C00008_INCLUDED_ 54 | #define LIBSOCKET_H_53FF16DE_4A25_11E5_917E_005056C00008_INCLUDED_ 55 | 56 | //////////////////////////////////////////////////////////// 57 | #if defined(TARGET_WINDOWS) 58 | #define TARGET_DEFINED 59 | #endif 60 | 61 | #if defined(TARGET_LINUX) 62 | #define TARGET_DEFINED 63 | #endif 64 | 65 | #ifndef TARGET_DEFINED 66 | #error "Define TARGET_WINDOWS or TARGET_LINUX first" 67 | #endif 68 | 69 | 70 | //////////////////////////////////////////////////////////// 71 | #ifdef TARGET_WINDOWS 72 | #include 73 | #include 74 | #include 75 | 76 | typedef int socklen_t; 77 | typedef SOCKET socket_t; 78 | typedef double timeout_t;//seconds 79 | typedef struct sockaddr sockaddr; 80 | 81 | #define WAITFD_R 1 //recv 82 | #define WAITFD_W 2 //send 83 | #define WAITFD_E 4 //error 84 | #define WAITFD_C (WAITFD_E|WAITFD_W) //connect 85 | 86 | #define SOCKET_INVALID (INVALID_SOCKET) 87 | 88 | #endif 89 | 90 | //////////////////////////////////////////////////////////// 91 | #ifdef TARGET_LINUX 92 | 93 | #include 94 | #include 95 | #include 96 | #include 97 | #include 98 | #include 99 | #include 100 | #include 101 | #include 102 | #include 103 | #include 104 | 105 | //@unistd.h 106 | //typedef int socklen_t; 107 | typedef int socket_t; 108 | typedef double timeout_t;//seconds 109 | typedef struct sockaddr sockaddr; 110 | 111 | #define SD_BOTH SHUT_RDWR 112 | #define SD_SEND SHUT_WR 113 | #define SD_RECEIVE SHUT_RD 114 | 115 | 116 | #define WAITFD_R 1 117 | #define WAITFD_W 2 118 | #define WAITFD_C (WAITFD_R|WAITFD_W) 119 | 120 | #define SOCKET_INVALID (-1) 121 | 122 | #endif 123 | 124 | 125 | //////////////////////////////////////////////////////////// 126 | // struct sockaddr { 127 | // unsigned short sa_family; 128 | // char sa_data[14]; 129 | // }; 130 | // 131 | // struct in_addr { 132 | // union { 133 | // struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b; 134 | // struct { u_short s_w1,s_w2; } S_un_w; 135 | // u_long S_addr; 136 | // } S_un; 137 | // #define s_addr S_un.S_addr 138 | // }; 139 | // 140 | // struct sockaddr_in { 141 | // short int sin_family; 142 | // unsigned short int sin_port; 143 | // struct in_addr sin_addr; 144 | // unsigned char sin_zero[8]; 145 | // }; 146 | // 147 | 148 | 149 | //////////////////////////////////////////////////////////// 150 | enum { 151 | IO_DONE = 0, /* operation completed successfully */ 152 | IO_TIMEOUT = -1, /* operation timed out */ 153 | IO_CLOSED = -2, /* the connection has been closed */ 154 | IO_UNKNOWN = -3 155 | }; 156 | 157 | //////////////////////////////////////// 158 | //system dependent initialize interface 159 | int socket_startup(void); 160 | int socket_cleanup(void); 161 | 162 | int socket_create(socket_t* ps, int domain, int type, int protocol); 163 | void socket_destroy(socket_t* ps); 164 | 165 | //client (default sync mode) 166 | int socket_connect(socket_t* ps, sockaddr *addr, socklen_t addr_len, timeout_t tm); 167 | 168 | //server (default async mode) 169 | int socket_bind(socket_t* ps, sockaddr *addr, socklen_t addr_len); 170 | int socket_listen(socket_t* ps, int backlog); 171 | int socket_accept(socket_t* ps, socket_t* pa, sockaddr *addr, 172 | socklen_t *addr_len, timeout_t tm); 173 | 174 | //send recv 175 | int socket_send(socket_t* ps, const char *data, size_t count, 176 | size_t *sent, timeout_t tm); 177 | int socket_recv(socket_t* ps, char *data, size_t count, size_t *got, timeout_t tm); 178 | const char *socket_ioerror(socket_t* ps, int err); 179 | 180 | // DNS: hostname -> ip 181 | //rDNS: ip -> hostname 182 | // 183 | //this two method socket_get_hostxxx is rDNS 184 | // 185 | // struct hostent{ 186 | // char * h_name; 187 | // char ** h_aliases; 188 | // short h_addrtype; 189 | // short h_length; 190 | // char ** h_addr_list; 191 | // }; 192 | // 193 | // struct hostent* lpHostEnt 194 | // in_addr ina; 195 | // ina.S_un.S_addr = inet_addr("127.0.0.1"); 196 | // lpHostEnt = gethostbyaddr((char*)&ina.S_un.S_addr, 4, AF_INET); 197 | int socket_gethostbyaddr(const char *ipaddr, socklen_t len, struct hostent **hp); 198 | 199 | //hostname: "www.baidu.com" 200 | int socket_gethostbyname(const char *hostname, struct hostent **hp); 201 | 202 | //////////////////////////////////////// 203 | //aync mode 204 | void socket_setnonblocking(socket_t* ps); 205 | void socket_setblocking(socket_t* ps); 206 | 207 | int socket_waitfd(socket_t* ps, int sw, timeout_t tm); 208 | int socket_select(socket_t* n, fd_set *rfds, fd_set *wfds, fd_set *efds, timeout_t tm); 209 | void socket_shutdown(socket_t* ps, int how); 210 | 211 | 212 | const char *socket_strerror(int err); 213 | 214 | #endif 215 | 216 | -------------------------------------------------------------------------------- /libsocket/usocket.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | * 25 | * this code copy and modify from luasocket, which license is MIT:) 26 | * @ref luasocket/libsocket.h 27 | * @ref luasocket/usocket.c 28 | * @ref luasocket/wsocket.c 29 | * 30 | * 31 | * LuaSocket 2.0.2 license 32 | * Copyright ?2004-2007 Diego Nehab 33 | * 34 | * Permission is hereby granted, free of charge, to any person obtaining a 35 | * copy of this software and associated documentation files (the "Software"), 36 | * to deal in the Software without restriction, including without limitation 37 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 38 | * and/or sell copies of the Software, and to permit persons to whom the 39 | * Software is furnished to do so, subject to the following conditions: 40 | * 41 | * The above copyright notice and this permission notice shall be included in 42 | * all copies or substantial portions of the Software. 43 | * 44 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 45 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 46 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 47 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 48 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 49 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 50 | * DEALINGS IN THE SOFTWARE. 51 | */ 52 | 53 | #include 54 | #include 55 | #include 56 | 57 | #include "libsocket.h" 58 | 59 | int socket_waitfd(socket_t* h, int sw, timeout_t tm) 60 | { 61 | int ret; 62 | fd_set rfds; 63 | fd_set wfds; 64 | fd_set* rp; 65 | fd_set* wp; 66 | struct timeval tv; 67 | struct timeval* tp; 68 | 69 | if (tm == 0) { 70 | return IO_TIMEOUT; 71 | } 72 | 73 | do { 74 | /* must set bits within loop, because select may have modifed them */ 75 | rp = wp = NULL; 76 | if (sw & WAITFD_R) { 77 | FD_ZERO(&rfds); FD_SET(*h, &rfds); rp = &rfds; 78 | } 79 | 80 | if (sw & WAITFD_W) { 81 | FD_ZERO(&wfds); FD_SET(*h, &wfds); wp = &wfds; 82 | } 83 | 84 | tp = NULL; 85 | if (tm >= 0.0) { 86 | tv.tv_sec = (int)tm; 87 | tv.tv_usec = (int)((tm-tv.tv_sec)*1.0e6); 88 | tp = &tv; 89 | } 90 | ret = select(*h+1, rp, wp, NULL, tp); 91 | 92 | } while (ret == -1 && errno == EINTR); 93 | 94 | if (ret == -1) { 95 | return errno; 96 | } 97 | 98 | if (ret == 0) { 99 | return IO_TIMEOUT; 100 | } 101 | 102 | if (sw == WAITFD_C && FD_ISSET(*h, &rfds)) { 103 | return IO_CLOSED; 104 | } 105 | 106 | return IO_DONE; 107 | } 108 | 109 | 110 | int socket_select(socket_t* n, fd_set *rfds, fd_set *wfds, fd_set *efds, timeout_t tm) 111 | { 112 | int ret; 113 | struct timeval tv; 114 | 115 | do { 116 | tv.tv_sec = (int) tm; 117 | tv.tv_usec = (int) ((tm - tv.tv_sec) * 1.0e6); 118 | 119 | /* timeout = 0 means no wait */ 120 | ret = select(*n+1, rfds, wfds, efds, tm >= 0.0 ? &tv: NULL); 121 | 122 | } while (ret < 0 && errno == EINTR); 123 | 124 | return ret; 125 | } 126 | 127 | int socket_startup(void) 128 | { 129 | /* instals a handler to ignore sigpipe or it will crash us */ 130 | signal(SIGPIPE, SIG_IGN); 131 | return 1; 132 | } 133 | 134 | int socket_cleanup(void) 135 | { 136 | return 1; 137 | } 138 | 139 | int socket_create(socket_t* h, int domain, int type, int protocol) 140 | { 141 | *h = socket(domain, type, protocol); 142 | 143 | if (*h != SOCKET_INVALID) { 144 | return IO_DONE; 145 | } else { 146 | return errno; 147 | } 148 | } 149 | 150 | void socket_destroy(socket_t* h) 151 | { 152 | if (*h != SOCKET_INVALID) { 153 | socket_setblocking(h); 154 | close(*h); 155 | *h = SOCKET_INVALID; 156 | } 157 | } 158 | 159 | void socket_shutdown(socket_t* h, int how) 160 | { 161 | socket_setblocking(h); 162 | shutdown(*h, how); 163 | socket_setnonblocking(h); 164 | } 165 | 166 | int socket_connect(socket_t* h, sockaddr *addr, socklen_t len, timeout_t tm) 167 | { 168 | int err; 169 | 170 | if (*h == SOCKET_INVALID) { 171 | return IO_CLOSED; 172 | } 173 | 174 | do { 175 | if (connect(*h, addr, len) == 0) { 176 | return IO_DONE; 177 | } 178 | } while ((err = errno) == EINTR); 179 | 180 | /* if connection failed immediately, return error code */ 181 | if (err != EINPROGRESS && err != EAGAIN) { 182 | return err; 183 | } 184 | 185 | /* zero timeout case optimization */ 186 | if (tm == 0) { 187 | return IO_TIMEOUT; 188 | } 189 | 190 | /* wait until we have the result of the connection attempt or timeout */ 191 | err = socket_waitfd(h, WAITFD_C, tm); 192 | if (err == IO_CLOSED) { 193 | if (recv(*h, (char *) &err, 0, 0) == 0) { 194 | return IO_DONE; 195 | } else { 196 | return errno; 197 | } 198 | 199 | } else { 200 | return err; 201 | } 202 | } 203 | 204 | int socket_bind(socket_t* h, sockaddr *addr, socklen_t len) 205 | { 206 | int err = IO_DONE; 207 | int on = 1; 208 | 209 | setsockopt(*h, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 210 | 211 | socket_setblocking(h); 212 | if (bind(*h, addr, len) < 0) { 213 | err = errno; 214 | } 215 | socket_setnonblocking(h); 216 | return err; 217 | } 218 | 219 | int socket_listen(socket_t* h, int backlog) 220 | { 221 | int err = IO_DONE; 222 | 223 | socket_setblocking(h); 224 | if (listen(*h, backlog)) { 225 | err = errno; 226 | } 227 | socket_setnonblocking(h); 228 | return err; 229 | } 230 | 231 | int socket_accept(socket_t* h, socket_t* pa, sockaddr* addr, socklen_t* len, timeout_t tm) 232 | { 233 | sockaddr daddr; 234 | socklen_t dlen; 235 | int err; 236 | 237 | dlen = sizeof(daddr); 238 | 239 | if (*h == SOCKET_INVALID) { 240 | return IO_CLOSED; 241 | } 242 | 243 | if (addr == NULL) { 244 | addr = &daddr; 245 | } 246 | 247 | if (len == NULL) { 248 | len = &dlen; 249 | } 250 | 251 | for ( ;; ) { 252 | if ((*pa = accept(*h, addr, len)) != SOCKET_INVALID) { 253 | return IO_DONE; 254 | } 255 | 256 | err = errno; 257 | if (err == EINTR) { 258 | continue; 259 | } 260 | 261 | if (err != EAGAIN && err != ECONNABORTED) { 262 | return err; 263 | } 264 | 265 | if ((err = socket_waitfd(h, WAITFD_R, tm)) != IO_DONE) { 266 | return err; 267 | } 268 | } 269 | 270 | /* can't reach here */ 271 | return IO_UNKNOWN; 272 | } 273 | 274 | int socket_send(socket_t* h, const char *data, size_t count, size_t *sent, timeout_t tm) 275 | { 276 | int err; 277 | long put; 278 | 279 | *sent = 0; 280 | 281 | if (*h == SOCKET_INVALID) { 282 | return IO_CLOSED; 283 | } 284 | 285 | /* loop until we send something or we give up on error */ 286 | for ( ;; ) { 287 | put = (long) send(*h, data, count, 0); 288 | if (put > 0) { 289 | *sent = put; 290 | return IO_DONE; 291 | } 292 | 293 | err = errno; 294 | /* send can't really return 0, 295 | * but EPIPE means the connection was 296 | * closed 297 | */ 298 | if (put == 0 || err == EPIPE) { 299 | return IO_CLOSED; 300 | } 301 | 302 | /* we call was interrupted, just try again */ 303 | if (err == EINTR) { 304 | continue; 305 | } 306 | 307 | /* if failed fatal reason, report error */ 308 | if (err != EAGAIN) { 309 | return err; 310 | } 311 | 312 | /* wait until we can send something or we timeout */ 313 | if ((err = socket_waitfd(h, WAITFD_W, tm)) != IO_DONE) { 314 | return err; 315 | } 316 | } 317 | 318 | /* can't reach here */ 319 | return IO_UNKNOWN; 320 | } 321 | 322 | int socket_recv(socket_t* h, char *data, size_t count, size_t *got, timeout_t tm) 323 | { 324 | int err; 325 | long taken; 326 | 327 | *got = 0; 328 | 329 | if (*h == SOCKET_INVALID) { 330 | return IO_CLOSED; 331 | } 332 | 333 | for ( ;; ) { 334 | taken = (long) recv(*h, data, count, 0); 335 | if (taken > 0) { 336 | *got = taken; 337 | return IO_DONE; 338 | } 339 | 340 | err = errno; 341 | if (taken == 0) { 342 | return IO_CLOSED; 343 | } 344 | 345 | if (err == EINTR) { 346 | continue; 347 | } 348 | 349 | if (err != EAGAIN) { 350 | return err; 351 | } 352 | 353 | if ((err = socket_waitfd(h, WAITFD_R, tm)) != IO_DONE) { 354 | return err; 355 | } 356 | } 357 | 358 | return IO_UNKNOWN; 359 | } 360 | 361 | void socket_setblocking(socket_t* h) 362 | { 363 | int flags = fcntl(*h, F_GETFL, 0); 364 | flags &= (~(O_NONBLOCK)); 365 | fcntl(*h, F_SETFL, flags); 366 | } 367 | 368 | void socket_setnonblocking(socket_t* h) 369 | { 370 | int flags = fcntl(*h, F_GETFL, 0); 371 | flags |= O_NONBLOCK; 372 | fcntl(*h, F_SETFL, flags); 373 | } 374 | 375 | int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) 376 | { 377 | *hp = gethostbyaddr(addr, len, AF_INET); 378 | if (*hp) { 379 | return IO_DONE; 380 | } else if (h_errno) { 381 | return h_errno; 382 | } else if (errno) { 383 | return errno; 384 | } else { 385 | return IO_UNKNOWN; 386 | } 387 | } 388 | 389 | int socket_gethostbyname(const char *hostname, struct hostent **hp) 390 | { 391 | *hp = gethostbyname(hostname); 392 | 393 | if (*hp) { 394 | return IO_DONE; 395 | } else if (h_errno) { 396 | return h_errno; 397 | } else if (errno) { 398 | return errno; 399 | } else { 400 | return IO_UNKNOWN; 401 | } 402 | } 403 | 404 | const char* socket_strerror(int err) 405 | { 406 | switch (err) { 407 | case IO_DONE: return NULL; 408 | case IO_CLOSED: return "closed"; 409 | case IO_TIMEOUT: return "timeout"; 410 | 411 | case HOST_NOT_FOUND: return "host not found"; 412 | case EADDRINUSE: return "address already in use"; 413 | case EISCONN: return "already connected"; 414 | case EACCES: return "permission denied"; 415 | case ECONNREFUSED: return "connection refused"; 416 | case ECONNABORTED: return "closed"; 417 | case ECONNRESET: return "closed"; 418 | case ETIMEDOUT: return "timeout"; 419 | //default: return strerror(errno); 420 | default: return NULL; 421 | } 422 | } 423 | 424 | 425 | 426 | 427 | 428 | -------------------------------------------------------------------------------- /memo: -------------------------------------------------------------------------------- 1 | #/bin/bash 2 | # 3 | # I try working on bitbucket private repo, 4 | # then publish to github, try to avoid log mess. 5 | # 6 | # First Create project on github.com, then import to bitbucket.org 7 | # And make sure github.com/master eq bitbucket.org/master! 8 | # 9 | 10 | #tracking github repo on bitbucket 11 | ~$ git clone git@bitbucket.org:buaabyl/dukserver.git dukserver.bitbukcet 12 | ~$ cd dukserver.bitbucket 13 | dukserver.bitbucket$ git remote add github.com git@github.com:buaabyl/dukserver.git 14 | dukserver.bitbucket$ git fetch github.com 15 | dukserver.bitbucket$ cd .. 16 | 17 | #tracking bitbucket repo on github 18 | ~$ git clone git@github.com:buaabyl/dukserver.git dukserver.github 19 | ~$ cd dukserver.github 20 | dukserver.github$ git remote add bitbucket.org git@bitbucket.org:buaabyl/dukserver.git 21 | dukserver.github$ git fetch bitbucket.org 22 | dukserver.github$ cd .. 23 | 24 | #working on bitbucket, publish to github, so bitbucket using rebase not merge 25 | ~$ cd dukserver.bitbucket 26 | #fix bug or modify, remember push to server avoid data lost. 27 | dukserver.bitbucket$ git co -b working 28 | dukserver.bitbucket$ git push --set-upstream origin working 29 | 30 | dukserver.bitbucket$ git co master 31 | dukserver.bitbucket$ git fetch github.com 32 | dukserver.bitbucket$ git merge github.com/master 33 | 34 | dukserver.bitbucket$ git co working 35 | dukserver.bitbucket$ git rebase master 36 | 37 | dukserver.bitbucket$ git co master 38 | dukserver.bitbucket$ git merge working 39 | dukserver.bitbucket$ git branch working --delete 40 | dukserver.bitbucket$ git push origin :working 41 | 42 | dukserver.bitbucket$ git push 43 | 44 | dukserver.bitbucket$ cd .. 45 | 46 | #publish 47 | ~$ cd dukserver.github 48 | dukserver.github$ git fetch bitbucket.org 49 | dukserver.github$ git merge bitbucket.org/master 50 | dukserver.github$ git push 51 | dukserver.github$ cd .. 52 | 53 | -------------------------------------------------------------------------------- /test/duk_server.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "libsocket.h" 33 | #include "libhttp.h" 34 | #include "duktape.h" 35 | #include "dukpylib.h" 36 | #include "wsgi_server.h" 37 | 38 | void custom_init0(wsgi_handle_t* srv, void* param) 39 | { 40 | printf("%s(%8p)\n", "custom_init0", param); 41 | } 42 | 43 | void custom_init1(wsgi_handle_t* srv, void* param) 44 | { 45 | printf("%s(%8p)\n", "custom_init1", param); 46 | } 47 | 48 | void custom_fini0(wsgi_handle_t* srv, void* param) 49 | { 50 | printf("%s(%8p)\n", "custom_fini0", param); 51 | } 52 | 53 | void custom_fini1(wsgi_handle_t* srv, void* param) 54 | { 55 | printf("%s(%8p)\n", "custom_fini1", param); 56 | } 57 | 58 | int server(int argc, char* argv[], char* env[]) 59 | { 60 | wsgi_handle_t* h; 61 | 62 | if (argc <= 0) { 63 | printf("Need argument!\n"); 64 | return -1; 65 | } 66 | 67 | h = wsgi_create("0.0.0.0", 1000); 68 | if (h == NULL) { 69 | return -1; 70 | } 71 | 72 | wsgi_add_initialize_chain(h, custom_init0, (void*)1); 73 | wsgi_add_finalize_chain(h, custom_fini0, (void*)2); 74 | 75 | wsgi_add_initialize_chain(h, custom_init1, (void*)3); 76 | wsgi_add_finalize_chain(h, custom_fini1, (void*)4); 77 | 78 | wsgi_start(h, argc, argv, env); 79 | 80 | getchar(); 81 | 82 | wsgi_close(h); 83 | 84 | return 0; 85 | } 86 | 87 | int main(int argc, char* argv[], char* env[]) 88 | { 89 | socket_startup(); 90 | http_init(); 91 | 92 | server(argc-1, argv+1, env); 93 | 94 | if (http_memory_usage() > 0) { 95 | printf("*memory leak:\n"); 96 | http_memory_dump(); 97 | } 98 | 99 | http_fini(); 100 | socket_cleanup(); 101 | 102 | return 0; 103 | } 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /test/put.php: -------------------------------------------------------------------------------- 1 | 12 | 13 | -------------------------------------------------------------------------------- /test/shell.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include "duktape.h" 31 | #include "dukpylib.h" 32 | 33 | static int myduk_compile_execute(duk_context *ctx) 34 | { 35 | int comp_flags = 0; 36 | 37 | duk_compile(ctx, comp_flags); 38 | 39 | duk_push_global_object(ctx); /* 'this' binding */ 40 | duk_call_method(ctx, 0); 41 | 42 | if (!duk_is_null_or_undefined(ctx, -1)) { 43 | fprintf(stdout, "%s\n", duk_to_string(ctx, -1)); 44 | fflush(stdout); 45 | } 46 | duk_pop(ctx); 47 | 48 | return 0; 49 | } 50 | 51 | static int myduk_get_stack_raw(duk_context *ctx) 52 | { 53 | const char* s; 54 | const char fmt[] = "ExceptionError: \"%s\"\n"; 55 | char* p; 56 | 57 | //////////////////////////////////////////////////////// 58 | //'throw' Exception 59 | if (duk_is_string(ctx, -1)) { 60 | s = duk_to_string(ctx, -1); 61 | p = (char*)malloc(sizeof(fmt) + strlen(s) + 1); 62 | sprintf(p, fmt, s); 63 | duk_pop(ctx); 64 | duk_push_lstring(ctx, p, strlen(p)); 65 | free(p); 66 | return 1; 67 | } 68 | 69 | //////////////////////////////////////////////////////// 70 | //Other exception 71 | if (!duk_is_object(ctx, -1)) { 72 | return 1; 73 | } 74 | if (!duk_has_prop_string(ctx, -1, "stack")) { 75 | return 1; 76 | } 77 | 78 | duk_get_prop_string(ctx, -1, "stack"); /* caller coerces */ 79 | duk_remove(ctx, -2); 80 | 81 | return 1; 82 | } 83 | 84 | void myduk_print_prefix(int nindent) 85 | { 86 | printf(".... "); 87 | 88 | while (nindent-- > 0) { 89 | printf(" ");//4 space 90 | } 91 | } 92 | 93 | void myduk_peval_stdin(duk_context* ctx) 94 | { 95 | int rc; 96 | char c; 97 | int nlen; 98 | int nindent = 0; 99 | static char buffer[2048]; 100 | 101 | while (1) { 102 | fprintf(stdout, "duk> "); 103 | fflush(stdout); 104 | nindent = 0; 105 | 106 | nlen = 0; 107 | while (1) { 108 | c = fgetc(stdin); 109 | if (nlen >= sizeof(buffer)-1) { 110 | nlen = -1; 111 | break; 112 | } 113 | if (c == EOF) { 114 | buffer[nlen] = '\0'; 115 | break; 116 | } 117 | if (c == '\n') { 118 | if (nlen > 0) { 119 | if (buffer[nlen-1] == '\n') { 120 | buffer[nlen] = '\0'; 121 | break; 122 | } else if ((nindent == 0) && (buffer[nlen-1] == ';')) { 123 | buffer[nlen] = '\0'; 124 | break; 125 | } else if (buffer[nlen-1] == '{') { 126 | nindent++; 127 | myduk_print_prefix(nindent); 128 | } else if (buffer[nlen-1] == '}') { 129 | nindent--; 130 | myduk_print_prefix(nindent); 131 | } else { 132 | myduk_print_prefix(nindent); 133 | } 134 | 135 | } else {//nlen <= 0 136 | continue; 137 | } 138 | } 139 | buffer[nlen++] = c; 140 | } 141 | 142 | if (nlen == -1) { 143 | break; 144 | } 145 | if (nlen == 0) { 146 | if (c == EOF) { 147 | break; 148 | } 149 | continue; 150 | } 151 | 152 | duk_push_lstring(ctx, buffer, nlen); 153 | duk_push_string(ctx, "input"); 154 | 155 | rc = duk_safe_call(ctx, myduk_compile_execute, 2 /*nargs*/, 1 /*nret*/); 156 | if (rc != DUK_EXEC_SUCCESS) { 157 | duk_safe_call(ctx, myduk_get_stack_raw, 1 /*nargs*/, 1 /*nrets*/); 158 | fprintf(stderr, "%s\n", duk_safe_to_string(ctx, -1)); 159 | fflush(stderr); 160 | } 161 | duk_pop(ctx); 162 | 163 | if (c == EOF) { 164 | break; 165 | } 166 | } 167 | } 168 | 169 | int main(int argc, char* argv[]) 170 | { 171 | duk_context* ctx; 172 | 173 | ctx = duk_create_heap_default(); 174 | dukopen_pylib(ctx); 175 | 176 | pylib_put_args(ctx, argc, argv); 177 | 178 | if (argc == 1) { 179 | myduk_peval_stdin(ctx); 180 | } else { 181 | pylib_include(ctx, argv[1]); 182 | } 183 | 184 | duk_destroy_heap(ctx); 185 | 186 | return 0; 187 | } 188 | 189 | -------------------------------------------------------------------------------- /test/shell2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include "libhttp.h" 31 | 32 | #include "duktape.h" 33 | #include "dukpylib.h" 34 | 35 | static int myduk_compile_execute(duk_context *ctx) 36 | { 37 | int comp_flags = 0; 38 | 39 | duk_compile(ctx, comp_flags); 40 | 41 | duk_push_global_object(ctx); /* 'this' binding */ 42 | duk_call_method(ctx, 0); 43 | 44 | if (!duk_is_null_or_undefined(ctx, -1)) { 45 | fprintf(stdout, "%s\n", duk_to_string(ctx, -1)); 46 | fflush(stdout); 47 | } 48 | duk_pop(ctx); 49 | 50 | return 0; 51 | } 52 | 53 | static int myduk_get_stack_raw(duk_context *ctx) 54 | { 55 | const char* s; 56 | const char fmt[] = "ExceptionError: \"%s\"\n"; 57 | char* p; 58 | 59 | //////////////////////////////////////////////////////// 60 | //'throw' Exception 61 | if (duk_is_string(ctx, -1)) { 62 | s = duk_to_string(ctx, -1); 63 | p = (char*)malloc(sizeof(fmt) + strlen(s) + 1); 64 | sprintf(p, fmt, s); 65 | duk_pop(ctx); 66 | duk_push_lstring(ctx, p, strlen(p)); 67 | free(p); 68 | return 1; 69 | } 70 | 71 | //////////////////////////////////////////////////////// 72 | //Other exception 73 | if (!duk_is_object(ctx, -1)) { 74 | return 1; 75 | } 76 | if (!duk_has_prop_string(ctx, -1, "stack")) { 77 | return 1; 78 | } 79 | 80 | duk_get_prop_string(ctx, -1, "stack"); /* caller coerces */ 81 | duk_remove(ctx, -2); 82 | 83 | return 1; 84 | } 85 | 86 | void myduk_print_prefix(int nindent) 87 | { 88 | printf(".... "); 89 | 90 | while (nindent-- > 0) { 91 | printf(" ");//4 space 92 | } 93 | } 94 | 95 | void myduk_peval_stdin(duk_context* ctx) 96 | { 97 | int rc; 98 | char c; 99 | int nlen; 100 | int nindent = 0; 101 | static char buffer[2048]; 102 | 103 | while (1) { 104 | fprintf(stdout, "duk> "); 105 | fflush(stdout); 106 | nindent = 0; 107 | 108 | nlen = 0; 109 | while (1) { 110 | c = fgetc(stdin); 111 | if (nlen >= sizeof(buffer)-1) { 112 | nlen = -1; 113 | break; 114 | } 115 | if (c == EOF) { 116 | buffer[nlen] = '\0'; 117 | break; 118 | } 119 | if (c == '\n') { 120 | if (nlen > 0) { 121 | if (buffer[nlen-1] == '\n') { 122 | buffer[nlen] = '\0'; 123 | break; 124 | } else if ((nindent == 0) && (buffer[nlen-1] == ';')) { 125 | buffer[nlen] = '\0'; 126 | break; 127 | } else if (buffer[nlen-1] == '{') { 128 | nindent++; 129 | myduk_print_prefix(nindent); 130 | } else if (buffer[nlen-1] == '}') { 131 | nindent--; 132 | myduk_print_prefix(nindent); 133 | } else { 134 | myduk_print_prefix(nindent); 135 | } 136 | 137 | } else {//nlen <= 0 138 | continue; 139 | } 140 | } 141 | buffer[nlen++] = c; 142 | } 143 | 144 | if (nlen == -1) { 145 | break; 146 | } 147 | if (nlen == 0) { 148 | if (c == EOF) { 149 | break; 150 | } 151 | continue; 152 | } 153 | 154 | duk_push_lstring(ctx, buffer, nlen); 155 | duk_push_string(ctx, "input"); 156 | 157 | rc = duk_safe_call(ctx, myduk_compile_execute, 2 /*nargs*/, 1 /*nret*/); 158 | if (rc != DUK_EXEC_SUCCESS) { 159 | duk_safe_call(ctx, myduk_get_stack_raw, 1 /*nargs*/, 1 /*nrets*/); 160 | fprintf(stderr, "%s\n", duk_safe_to_string(ctx, -1)); 161 | fflush(stderr); 162 | } 163 | duk_pop(ctx); 164 | 165 | if (c == EOF) { 166 | break; 167 | } 168 | } 169 | } 170 | 171 | static void* _duk_alloc(void *udata, duk_size_t size) 172 | { 173 | void* p; 174 | p = http_malloc(size); 175 | 176 | return p; 177 | } 178 | 179 | static void* _duk_realloc(void *udata, void *ptr, duk_size_t size) 180 | { 181 | void* p; 182 | 183 | p = http_realloc(ptr, size); 184 | 185 | return p; 186 | } 187 | 188 | static void _duk_free(void *udata, void *ptr) 189 | { 190 | http_free(ptr); 191 | } 192 | 193 | 194 | int main(int argc, char* argv[]) 195 | { 196 | duk_context* ctx; 197 | 198 | socket_startup(); 199 | http_init(); 200 | 201 | //ctx = duk_create_heap_default(); 202 | ctx = duk_create_heap(_duk_alloc, _duk_realloc, _duk_free, NULL, NULL); 203 | dukopen_pylib(ctx); 204 | 205 | pylib_put_args(ctx, argc, argv); 206 | 207 | if (argc == 1) { 208 | myduk_peval_stdin(ctx); 209 | } else { 210 | pylib_include(ctx, argv[1]); 211 | } 212 | 213 | duk_destroy_heap(ctx); 214 | 215 | if (http_memory_usage() > 0) { 216 | printf("*memory leak:\n"); 217 | http_memory_dump(); 218 | } 219 | 220 | http_fini(); 221 | socket_cleanup(); 222 | 223 | return 0; 224 | } 225 | 226 | -------------------------------------------------------------------------------- /test/simple_client.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "libsocket.h" 33 | #include "libhttp.h" 34 | 35 | int test_get(const char* host, const char* ip, int port) 36 | { 37 | http_connection_t* conn; 38 | http_content_t* req; 39 | http_content_t* res; 40 | 41 | conn = http_connect(host, ip, port); 42 | if (conn == NULL) { 43 | return -1; 44 | } 45 | 46 | //send request 47 | req = http_content_new(); 48 | http_start_request(req, "GET", "/index.html"); 49 | http_header(req, "username", "fish"); 50 | http_write(req, "hello", 5); 51 | http_send_request(conn, req); 52 | 53 | http_dump_content(req); 54 | http_content_delete(req); 55 | req = NULL; 56 | 57 | //receive response 58 | res = http_recv_response(conn); 59 | if (res) { 60 | http_dump_content(res); 61 | http_content_delete(res); 62 | res = NULL; 63 | } 64 | 65 | http_close(conn); 66 | 67 | return 0; 68 | } 69 | 70 | int test_post(const char* host, const char* ip, int port) 71 | { 72 | http_connection_t* conn; 73 | http_content_t* req; 74 | http_content_t* res; 75 | http_map_t* m; 76 | char* form_buf; 77 | int form_len; 78 | 79 | m = http_map_new(100); 80 | http_map_set(m, "id", NULL); 81 | http_map_set(m, "name", "fish"); 82 | http_map_set(m, "pass", "123"); 83 | http_map_set(m, "refurl", "http://www.example.com/register.html?q=new"); 84 | form_len = http_urlencode(m, &form_buf); 85 | 86 | conn = http_connect(host, ip, port); 87 | if (conn == NULL) { 88 | http_free(form_buf); 89 | http_map_delete(m); 90 | return -1; 91 | } 92 | 93 | //send request 94 | req = http_content_new(); 95 | http_start_request(req, "POST", "/index.html"); 96 | http_header(req, "Content-Type", "application/x-www-form-urlencoded"); 97 | http_write(req, form_buf, form_len); 98 | http_send_request(conn, req); 99 | 100 | http_dump_content(req); 101 | http_content_delete(req); 102 | req = NULL; 103 | 104 | http_free(form_buf); 105 | http_map_delete(m); 106 | 107 | //receive response 108 | res = http_recv_response(conn); 109 | if (res) { 110 | http_dump_content(res); 111 | http_content_delete(res); 112 | res = NULL; 113 | } 114 | 115 | http_close(conn); 116 | 117 | return 0; 118 | } 119 | 120 | int main(int argc, char* argv[]) 121 | { 122 | socket_startup(); 123 | http_init(); 124 | 125 | //test_get("www.example.com", "127.0.0.1", 1000); 126 | test_post("www.example.com", "127.0.0.1", 1000); 127 | 128 | if (http_memory_usage() > 0) { 129 | printf("*memory leak:\n"); 130 | http_memory_dump(); 131 | } 132 | 133 | http_fini(); 134 | socket_cleanup(); 135 | 136 | return 0; 137 | } 138 | 139 | -------------------------------------------------------------------------------- /test/simple_server.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright 2005-2016 Buaabyl 4 | * 5 | * (http://opensource.org/licenses/MIT) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "libsocket.h" 33 | #include "libhttp.h" 34 | 35 | #ifdef TARGET_WINDOWS 36 | void start_thread(void (*f)(void*), void* param) 37 | { 38 | _beginthread(f, 0, param); 39 | } 40 | #endif 41 | 42 | int process(http_connection_t* conn) 43 | { 44 | http_content_t* req; 45 | http_content_t* res; 46 | const char* method; 47 | const char* content_type; 48 | 49 | http_map_t* m; 50 | http_map_iter_t iter; 51 | 52 | //receive request 53 | req = http_recv_request(conn); 54 | if (req == NULL) { 55 | return -1; 56 | } 57 | http_dump_content(req); 58 | 59 | method = http_map_get(req->dict, HTTP_METHOD); 60 | content_type = http_map_get(req->dict, "Content-Type"); 61 | if (method && content_type) { 62 | if (strcmp(method, "POST") == 0) { 63 | if (strcmp(content_type, HTTP_DEFAULT_FORM_ENCODED) == 0) { 64 | m = http_urldecode(req->body->ptr, req->body->size); 65 | if (m) { 66 | for (http_map_begin(m, &iter); 67 | http_map_valid(&iter); 68 | http_map_next(&iter)) 69 | { 70 | printf(" \"%s\" = \"%s\"\n", iter.k, iter.v); 71 | } 72 | 73 | http_map_delete(m); 74 | m = NULL; 75 | } 76 | } else { 77 | printf("Error: not support form encoded \"%s\"\n", content_type); 78 | } 79 | } 80 | } 81 | 82 | http_content_delete(req); 83 | req = NULL; 84 | 85 | //send response 86 | res = http_content_new(); 87 | http_start_response(res, 200); 88 | http_header(res, "username", "fish"); 89 | http_write(res, "hello world!", 12); 90 | http_send_response(conn, res); 91 | http_content_delete(res); 92 | res = NULL; 93 | 94 | return 0; 95 | } 96 | 97 | void thread(void* param) 98 | { 99 | http_connection_t* conn = (http_connection_t*)param; 100 | 101 | process(conn); 102 | 103 | httpd_close(conn); 104 | conn = NULL; 105 | } 106 | 107 | int server(void) 108 | { 109 | httpd_server_t* srv; 110 | http_connection_t* conn; 111 | 112 | srv = httpd_create(NULL, "0.0.0.0", 1000); 113 | if (srv == NULL) { 114 | printf("Can't create httpd!\n"); 115 | return -1; 116 | } 117 | 118 | while (1) { 119 | conn = httpd_accept(srv); 120 | if (conn == NULL) { 121 | break; 122 | } 123 | 124 | printf("*connected %s:%d\n", conn->host, conn->port); 125 | 126 | #ifdef TARGET_WINDOWS 127 | start_thread(thread, conn); 128 | #else 129 | thread(conn); 130 | #endif 131 | 132 | printf("*disconnected\n"); 133 | } 134 | 135 | httpd_destroy(srv); 136 | srv = NULL; 137 | 138 | return 0; 139 | } 140 | 141 | int main(int argc, char* argv[]) 142 | { 143 | socket_startup(); 144 | http_init(); 145 | 146 | printf("*memory %8d bytes\n", http_memory_usage()); 147 | 148 | server(); 149 | 150 | if (http_memory_usage() > 0) { 151 | printf("*memory leak:\n"); 152 | http_memory_dump(); 153 | } 154 | 155 | http_fini(); 156 | socket_cleanup(); 157 | 158 | return 0; 159 | } 160 | 161 | 162 | 163 | -------------------------------------------------------------------------------- /test/wsgi_app.js: -------------------------------------------------------------------------------- 1 | //reserver global name 2 | // "__file__" as script file path 3 | // "__http_response_status__" 4 | // "__http_response_headers__" 5 | // 6 | //environ is '__cobject_map__', not array! 7 | function application(environ, start_response) 8 | { 9 | print(__file__); 10 | 11 | for (var k in environ) { 12 | var v = environ[k]; 13 | print( 14 | "\"" + k + "\"" + 15 | ": " + 16 | "{" + typeof(v) + "} " + 17 | "\"" + v + "\"" 18 | ); 19 | }; 20 | 21 | var form = environ['wsgi.post'] 22 | if (form) { 23 | print("POST:"); 24 | for (var k in form) { 25 | var v = form[k]; 26 | print(" \"" + k + "\"" + ": " + "\"" + v + "\""); 27 | }; 28 | } 29 | 30 | start_response(200, {"Name":"jush"}); 31 | 32 | var _subprocess = require('_subprocess'); 33 | var ps = _subprocess.open('uptime'); 34 | var stdout; 35 | while (1) { 36 | var out = ps.stdout.read(); 37 | if (out == null) { 38 | break; 39 | } 40 | stdout += out; 41 | } 42 | 43 | return stdout; 44 | } 45 | 46 | -------------------------------------------------------------------------------- /testjs/_file_be_included1.js: -------------------------------------------------------------------------------- 1 | throw 'Must found "_test_include/_file_be_include1.js" first, not this file!'; -------------------------------------------------------------------------------- /testjs/_file_be_included2.js: -------------------------------------------------------------------------------- 1 | function test() { 2 | return "hello world!"; 3 | } 4 | 5 | print('__file__: ' + __file__); 6 | for (var fn in Modules.trace) { 7 | print(' .' + fn + ': "' + __files__[fn] + '"'); 8 | } 9 | 10 | print('include("test_include/_file_be_included3.js")'); 11 | include('test_include/_file_be_included3.js'); 12 | 13 | var base = 100; 14 | print('base + 1 + 1 = ' + eval('1+1+base')); 15 | 16 | test(); 17 | 18 | -------------------------------------------------------------------------------- /testjs/_file_be_included4.js: -------------------------------------------------------------------------------- 1 | print('__file__: ' + __file__); 2 | for (var fn in Modules.trace) { 3 | print(' .' + fn + ': "' + __files__[fn] + '"'); 4 | } 5 | 6 | -------------------------------------------------------------------------------- /testjs/_mod_be_require.js: -------------------------------------------------------------------------------- 1 | exports.hello = function() { 2 | return "Hi"; 3 | } 4 | -------------------------------------------------------------------------------- /testjs/cp_stdin_to_stdout.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 buaa.byl@gmail.com 3 | * 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2, or (at your option) 8 | * any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; see the file COPYING. If not, write to 17 | * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 18 | */ 19 | 20 | #include 21 | #include 22 | 23 | int main(int argc, char* argv[]) 24 | { 25 | printf("*kk\n"); 26 | 27 | while (!feof(stdin)) { 28 | putchar(fgetc(stdin)); 29 | fflush(stdout); 30 | //break; 31 | } 32 | 33 | return 0; 34 | } 35 | 36 | -------------------------------------------------------------------------------- /testjs/test_array.js: -------------------------------------------------------------------------------- 1 | //create an unnamed object, not create dict! 2 | d = {"name0":"fish", "name1":"ken"}; 3 | print(d instanceof Array); 4 | print(Object.prototype.toString.call(d)); 5 | print("Object.getOwnPropertyNames({}):", Object.getOwnPropertyNames(d)); 6 | print("Object.keys({}):", Object.keys(d)); 7 | print(); 8 | 9 | //create array 10 | l0 = [1,2,3,4]; 11 | print(l0 instanceof Array); 12 | print(Object.prototype.toString.call(l0)); 13 | print("Object.getOwnPropertyNames(l0):", Object.getOwnPropertyNames(l0)); 14 | print("Object.keys(l0):", Object.keys(l0)); 15 | print(); 16 | 17 | //create array 18 | l1 = new Array(1,2,3,4); 19 | print(l1 instanceof Array); 20 | print(Object.prototype.toString.call(l1)); 21 | print("Object.getOwnPropertyNames(l1):", Object.getOwnPropertyNames(l1)); 22 | print("Object.keys(l1):", Object.keys(l1)); 23 | print(); 24 | 25 | //create array 26 | dict = new Array(); 27 | dict["name0"] = "david"; 28 | dict["name1"] = "john"; 29 | print(dict instanceof Array); 30 | print(Object.prototype.toString.call(dict)); 31 | print("Object.getOwnPropertyNames(dict):", Object.getOwnPropertyNames(dict)); 32 | print("Object.keys(dict):", Object.keys(dict)); 33 | print(); 34 | 35 | buf = Duktape.Buffer("string"); 36 | print(typeof(buf)); 37 | for (var c in buf) { 38 | print('', c); 39 | } 40 | print("=="); 41 | res = new Array(); 42 | for (i = 0;i < 5;i++) { 43 | res.push(i); 44 | } 45 | print(Object.prototype.toString.call(res)); 46 | print(res.join('')); 47 | 48 | -------------------------------------------------------------------------------- /testjs/test_dir_globals.js: -------------------------------------------------------------------------------- 1 | print("ord: " + ord('a')); 2 | print("chr: " + chr(0x64)); 3 | print("hello"); 4 | 5 | var s = 'sdfsdf.111'; 6 | print('s.split = ' + s.split); 7 | print('s.split.name = ' + s.split.name); 8 | print(); 9 | 10 | var ll = s.split('.'); 11 | print('typeof(ll) = ' + typeof(ll)); 12 | print(ll); 13 | print(); 14 | 15 | print("typeof(globals)=", typeof(globals)); 16 | print('globals:'); 17 | var l = globals(); 18 | for (var v in l) { 19 | print(' ["' + v + '"] = (' + typeof(l[v]) + ') ' + l[v]); 20 | } 21 | print(); 22 | 23 | print("typeof(Duktape) = " + typeof(Duktape)); 24 | print("dir(Duktape):"); 25 | var m = dir(Duktape, 2); 26 | for (var k in m) { 27 | print(' ' + k + ': ' + m[k]); 28 | } 29 | 30 | 31 | -------------------------------------------------------------------------------- /testjs/test_error.js: -------------------------------------------------------------------------------- 1 | var sys = require('sys'); 2 | 3 | var s = 'sys.args: '; 4 | for (var i = 0;i < sys.args.length;i++) { 5 | s += sys.args[i] + ", "; 6 | } 7 | print(s); 8 | 9 | try { 10 | print('throw "exception"'); 11 | throw Array("throw Array"); 12 | throw "throw string: exception"; 13 | print("ok"); 14 | } catch (estr) { 15 | if (estr instanceof Object) { 16 | print('catched object: ' + estr); 17 | } else { 18 | print('catched: ' + estr); 19 | } 20 | This_will_cause_ReferenceError; 21 | } 22 | 23 | 24 | -------------------------------------------------------------------------------- /testjs/test_function.js: -------------------------------------------------------------------------------- 1 | print("Duktape.version = " + Duktape.version); 2 | 3 | function small_test() 4 | { 5 | var i; 6 | var n = 2; 7 | for (i = 0;i < n;i++) { 8 | print(chr(ord('0') + i)); 9 | } 10 | 11 | v = new Array(1,2,3,4); 12 | print(v); 13 | 14 | print("list:"); 15 | l = [1,2,"string"]; 16 | for (var val in l) { 17 | print('', val); 18 | } 19 | 20 | print("dictory:"); 21 | d = {"name":"fish", "id":122}; 22 | for (var key in d) { 23 | print('', typeof(key), key, d[key]); 24 | } 25 | 26 | print("name" in d); 27 | print("user" in d); 28 | } 29 | 30 | small_test(); 31 | 32 | -------------------------------------------------------------------------------- /testjs/test_include.js: -------------------------------------------------------------------------------- 1 | print("__file__:" + __file__); 2 | 3 | var res = globals(); 4 | print("globals():"); 5 | for (var k in res) { 6 | print(" " + k + ": " + res[k]); 7 | } 8 | print(); 9 | 10 | print("include('./test_include/_file_be_included.js')"); 11 | include("./test_include/_file_be_included.js"); 12 | 13 | var sys = require('sys'); 14 | if (sys.args.length > 1) { 15 | if (os.path.exists(sys.args[1])) { 16 | var st = os.stat(sys.args[1]); 17 | print(sys.args[1].decode('UTF-8').encode('GBK')); 18 | print(st); 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /testjs/test_include/_file_be_included.js: -------------------------------------------------------------------------------- 1 | print('__file__:' + __file__); 2 | for (var fn in Modules.trace) { 3 | print(' .' + fn + ': "' + __files__[fn] + '"'); 4 | } 5 | print('hello world\n'); 6 | print('sys.args: ' + Modules.sys.args); 7 | 8 | //Duktape内部的字符编码是UTF-8的, 9 | //并且这个源文件也是UTF-8的。 10 | //下面将他写为UCS-2(Unicode 2字节编码小端模式) 11 | var f = Modules.fs.open('测试.tmp', 'wb'); 12 | f.write(chr(0xFF)); 13 | f.write(chr(0xFE)); 14 | f.write('测试一下'.decode('UTF-8')); 15 | f.close(); 16 | 17 | print('ord("1"): ' + ord('1')); 18 | print('chr(72): ' + chr(72)); 19 | print('hex(72): ' + hex(72)); 20 | 21 | print('include("_file_be_included1.js")'); 22 | include('_file_be_included1.js'); 23 | 24 | -------------------------------------------------------------------------------- /testjs/test_include/_file_be_included1.js: -------------------------------------------------------------------------------- 1 | print('__file__: ' + __file__); 2 | for (var fn in Modules.trace) { 3 | print(' .' + fn + ': "' + Modules.trace[fn] + '"'); 4 | } 5 | 6 | print('include("_file_be_included2.js")'); 7 | include('_file_be_included2.js'); 8 | 9 | 10 | for (var fn in Modules.trace) { 11 | print(' .' + fn + ': "' + Modules.trace[fn] + '"'); 12 | } 13 | 14 | var g = globals(); 15 | print("globals():"); 16 | for (var k in g) { 17 | print(' ' + k + ': ' + g[k]); 18 | } 19 | 20 | var os = require('os'); 21 | print(os.path.normpath('dir1/../dir2/test...file/')); 22 | print(os.path.abspath('dir1/../dir2/test...file')); 23 | -------------------------------------------------------------------------------- /testjs/test_include/_file_be_included3.js: -------------------------------------------------------------------------------- 1 | print('__file__: ' + __file__); 2 | for (var fn in Modules.trace) { 3 | print(' .' + fn + ': "' + __files__[fn] + '"'); 4 | } 5 | 6 | print('include("./_file_be_included4.js")'); 7 | include('./_file_be_included4.js'); 8 | -------------------------------------------------------------------------------- /testjs/test_include/_file_be_included4.js: -------------------------------------------------------------------------------- 1 | throw 'Must found "_file_be_include1.js" first, not this file in directory "test_include"!'; -------------------------------------------------------------------------------- /testjs/test_json.js: -------------------------------------------------------------------------------- 1 | //'jc' is standard json format, 'jx' is extend json format 2 | var fs = require('fs'); 3 | 4 | try{ 5 | var obj = {name: "fish", devices: ["macbook", "thinkpad", 'hp']}; 6 | //jx = Duktape.enc('jc', obj); 7 | jx = Duktape.enc('jc', obj, null, 4); 8 | fs.file_put_content('duk.json', jx); 9 | print(jx); 10 | 11 | jx = fs.file_get_content('duk.json'); 12 | var dec = Duktape.dec('jc', jx); 13 | print(dec.name); 14 | print(dec.devices); 15 | } catch (e) { 16 | print(e.stack); 17 | } 18 | 19 | -------------------------------------------------------------------------------- /testjs/test_os_path.js: -------------------------------------------------------------------------------- 1 | var os = require('os'); 2 | 3 | print(" os.getcwd(): " + 4 | os.getcwd()); 5 | 6 | print(" os.path.split('C:'): " + 7 | os.path.split('C:')); 8 | print(" os.path.split('C:/'): " + 9 | os.path.split('C:/')); 10 | print(" os.path.split('/ewfwef/ffff.js'): " + 11 | os.path.split('/ewfwef/ffff.js')); 12 | 13 | print(" os.path.splitext('/ewfwef/ffffjs'): " + 14 | os.path.splitext('/ewfwef/ffffjs')); 15 | print(" os.path.splitext('c:\\ewfwef\\ffff.js'): " + 16 | os.path.splitext('c:\\ewfwef\\ffff.js')); 17 | print(" os.path.splitext('c:/ewfwef/ffff.js'): " + 18 | os.path.splitext('c:/ewfwef/ffff.js')); 19 | 20 | print(" os.path.normpath('test/../.././hello.js'): " + 21 | os.path.normpath('test/../.././hello.js')); 22 | 23 | print(" os.path.abspath('test/../.././hello.js'): " + 24 | os.path.abspath('test/../.././hello.js')); 25 | 26 | print(" os.path.join('C:/', 'test', 'file.js')" + 27 | os.path.join('C:/', 'test', 'file.js')); 28 | 29 | -------------------------------------------------------------------------------- /testjs/test_regexp.js: -------------------------------------------------------------------------------- 1 | print("hello world\n"); 2 | 3 | function show_method(v) 4 | { 5 | var ddd = dir(v, 1); 6 | for (var k in ddd) { 7 | print(k + ": " + ddd[k]); 8 | } 9 | print(); 10 | } 11 | 12 | var str = "hello $name"; 13 | var newstr = str.replace(/\$name/g, 'david'); 14 | print(newstr); 15 | 16 | var r = /\W*(\d+)\W*x\W*(\d+)/g; 17 | //show_method(r); 18 | 19 | var txt = " 1 x8"; 20 | 21 | var res = r.exec(txt); 22 | 23 | print("txt: \"" + txt + "\""); 24 | if (res) { 25 | print("match"); 26 | print("res.length = " + res.length); 27 | 28 | for (var i = 0;i < res.length;i++) { 29 | print(" res[" + i + "] = " + res[i]); 30 | } 31 | print(); 32 | } else { 33 | print("not match"); 34 | } 35 | 36 | var params = new Array(); 37 | var res = " 1 x8".replace(/\W*(\d+)\W*x\W*(\d+)/g, function (s, s1, s2){ 38 | params.push(s1); 39 | params.push(s2); 40 | return s; 41 | }); 42 | print(params); 43 | 44 | 45 | print("replace:"); 46 | var res = "${status_code} ${status_message}".replace(/\$\{([^}]+)\}/g, function (s, s1){ 47 | print(s); 48 | print(s1); 49 | return s; 50 | }); 51 | print("replace-end"); 52 | 53 | function isdigit(s) 54 | { 55 | //float 56 | if (s.match(/^\W*\d+\.\d+\W*$/g)) { 57 | return true; 58 | } 59 | //interger 60 | if (s.match(/^\W*\d+\W*$/g)) { 61 | return true; 62 | } 63 | return false; 64 | } 65 | 66 | print(isdigit("2.34u")); 67 | -------------------------------------------------------------------------------- /testjs/test_require.js: -------------------------------------------------------------------------------- 1 | /* 2 | function modSearch(id, require, exports, module) { 3 | print("*modSearch(" + id + "," + require + "," + exports + "," + module + ")"); 4 | print("dir(module):"); 5 | for (var k in dir(module, 1)) { 6 | print(" *" + k + ':' + module[k]); 7 | } 8 | print("END"); 9 | 10 | if (id === 'foo') { 11 | return 'exports.hello = function() { print("Hello from foo!"); };'; 12 | } else if (id === 'bar') { 13 | return 'exports.hello = function() { print("Hello from bar!"); };'; 14 | } else if (id === 'fun') { 15 | return 'exports = function() { print("Hello from fun!"); };'; 16 | } else { 17 | //try load script 18 | var dirname = os.path.dirname(__file__); 19 | var fn = os.path.join(dirname, id); 20 | var absfn = os.path.abspath(fn); 21 | if (!os.path.isfile(absfn)) { 22 | dirname = os.getcwd(); 23 | fn = os.path.join(dirname, id); 24 | absfn = os.path.abspath(fn); 25 | if (!os.path.isfile(absfn)) { 26 | throw new Error('module not found: ' + id); 27 | } 28 | } 29 | 30 | var text = fs.file_get_content(absfn); 31 | print("load: " + absfn); 32 | 33 | return text; 34 | } 35 | throw new Error('module not found: ' + id); 36 | }; 37 | 38 | Duktape.modSearch = modSearch; 39 | */ 40 | 41 | print("globals():"); 42 | for (var k in globals()) { 43 | print(k + ':' + globals()[k]); 44 | } 45 | print("END"); 46 | 47 | var obj = require('_mod_be_require.js'); 48 | if (obj) { 49 | var m = dir(obj); 50 | for (var k in m) { 51 | print(k + ":" + m[k]); 52 | } 53 | obj.hello(); 54 | } 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /testjs/test_split.js: -------------------------------------------------------------------------------- 1 | s = "hello;world;"; 2 | var l = s.split(";"); 3 | 4 | for (var idx in l) { 5 | print("index: " + idx + ", \"" + l[idx] + "\""); 6 | } 7 | 8 | print(s); 9 | -------------------------------------------------------------------------------- /testjs/test_subprocess.js: -------------------------------------------------------------------------------- 1 | var _subprocess = require('_subprocess'); 2 | var subprocess = new Object(); 3 | 4 | subprocess.CalledProcessError = function (returncode, cmd, stdout) { 5 | this.returncode = returncode; 6 | this.cmd = cmd; 7 | this.stdout = stdout; 8 | } 9 | 10 | subprocess.call = function() { 11 | var ps; 12 | var returncode; 13 | var out; 14 | var args = new Array(); 15 | 16 | for (var i = 0;i < arguments.length;i++) { 17 | args.push(arguments[i]); 18 | } 19 | ps = _subprocess.open(args); 20 | 21 | while (1) { 22 | var res = ps.stdout.read(); 23 | if (res == null) { 24 | break; 25 | } 26 | out = out + res; 27 | } 28 | returncode = ps.wait(); 29 | if (returncode != 0) { 30 | throw new subprocess.CalledProcessError(returncode, args, out); 31 | } 32 | 33 | ps.close(); 34 | return returncode; 35 | } 36 | 37 | subprocess.check_output = function() { 38 | var ps; 39 | var returncode; 40 | var out; 41 | var args = new Array(); 42 | 43 | for (var i = 0;i < arguments.length;i++) { 44 | args.push(arguments[i]); 45 | } 46 | ps = _subprocess.open(args); 47 | 48 | while (1) { 49 | var res = ps.stdout.read(); 50 | if (res == null) { 51 | break; 52 | } 53 | out = out + res; 54 | } 55 | returncode = ps.wait(); 56 | if (returncode != 0) { 57 | throw new subprocess.CalledProcessError(returncode, args, out); 58 | } 59 | 60 | ps.close(); 61 | return out 62 | } 63 | 64 | print('subprocess.call("ls.exe"):'); 65 | var ret = subprocess.call("ls.exe"); 66 | print('return ' + ret); 67 | print(); 68 | 69 | print('subprocess.check_output("ls.exe"):'); 70 | var ret = subprocess.check_output("ls.exe"); 71 | print('return "' + ret + '"'); 72 | 73 | try { 74 | subprocess.check_output('test_subprocess_runner', 'error'); 75 | } catch (e) { 76 | if (e instanceof subprocess.CalledProcessError) { 77 | print('CalledProcessError:'); 78 | print(' ' + e.returncode); 79 | print(' ' + e.cmd); 80 | print(' "' + e.stdout + '"'); 81 | } else { 82 | print(e); 83 | } 84 | } 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /testjs/test_subprocess_cat.js: -------------------------------------------------------------------------------- 1 | var os = require('os'); 2 | var _subprocess = require('_subprocess'); 3 | 4 | var ps; 5 | if (os.name == 'posix') { 6 | ps = _subprocess.open('cat'); 7 | } else { 8 | ps = _subprocess.open('cat.exe'); 9 | } 10 | 11 | var cnt = 10; 12 | while (cnt-- > 0) { 13 | ps.stdin.write('hello' + cnt + '\n'); 14 | var out = ps.stdout.read(); 15 | if (out == null) { 16 | break; 17 | } 18 | print('"' + out + '"'); 19 | } 20 | 21 | print('close'); 22 | ps.close(); 23 | 24 | 25 | -------------------------------------------------------------------------------- /testjs/test_subprocess_commandline.js: -------------------------------------------------------------------------------- 1 | var os = require('os'); 2 | var sys = require('sys'); 3 | var _subprocess = require('_subprocess'); 4 | 5 | var args = Array(); 6 | 7 | for (var i = 1;i < sys.args.length;i++) { 8 | args.push(sys.args[i]); 9 | } 10 | 11 | var res = _subprocess.open(args); 12 | 13 | var m = dir(res); 14 | print('dir(res):'); 15 | for (var k in m) { 16 | print(' ' + k + ': ' + m[k]); 17 | } 18 | print(); 19 | 20 | //read stdout 21 | while (1) { 22 | var out = res.stdout.read(); 23 | if (out == null) { 24 | break; 25 | } 26 | print('"' + out + '"'); 27 | } 28 | 29 | print('commandline: ' + res.cmd); 30 | print('returncode: ' + res.wait()); 31 | 32 | 33 | -------------------------------------------------------------------------------- /testjs/test_subprocess_err.js: -------------------------------------------------------------------------------- 1 | include('test_subprocess.js'); 2 | 3 | try { 4 | var out = subprocess.check_output("test_subprocess_runner"); 5 | var out = subprocess.check_output("test_subprocess_runner", "error"); 6 | print(out); 7 | } catch (e) { 8 | if (e instanceof subprocess.CalledProcessError) { 9 | print('subprocess.CalledProcessError:'); 10 | print(' e.returncode = ' + e.returncode); 11 | print(' e.cmd = ' + e.cmd); 12 | print(' e.output = "' + e.output + '"'); 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /testjs/test_subprocess_runner.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 buaa.byl@gmail.com 3 | * 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2, or (at your option) 8 | * any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; see the file COPYING. If not, write to 17 | * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 18 | */ 19 | 20 | #include 21 | #include 22 | 23 | int main(int argc, char* argv[]) 24 | { 25 | printf("test_subprocess_runner\n"); 26 | 27 | if (argc == 1) { 28 | return 0; 29 | } 30 | 31 | if (strcmp(argv[1], "error") == 0) { 32 | return -1; 33 | } 34 | 35 | return 0; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /testjs/test_throw.js: -------------------------------------------------------------------------------- 1 | try { 2 | print("Ok\n"); 3 | not_exist_function(); 4 | throw "Exception"; 5 | print("Not reach\n"); 6 | 7 | } catch (e) { 8 | print('typeof(e) = ' + typeof(e)); 9 | if (typeof(e) == 'object') { 10 | print(e.stack); 11 | print(); 12 | print(e.name + ": " + e.message); 13 | print('Location: ' + e.fileName + ":" + e.lineNumber); 14 | 15 | } else { 16 | print(e); 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /testjs/test_time.js: -------------------------------------------------------------------------------- 1 | var time = require('time'); 2 | 3 | print(" time.time(): " + time.time()); 4 | print(" time.localtime(): " + time.localtime()); 5 | 6 | print("strftime: " + time.strftime("%Y-%m-%d")); 7 | print(time.ctime()); 8 | 9 | -------------------------------------------------------------------------------- /testjs/test_unicode.js: -------------------------------------------------------------------------------- 1 | //duktape只支持UTF-8编码! 2 | print("测试"); 3 | print("测试".decode('UTF-8').encode('GBK')); 4 | --------------------------------------------------------------------------------