Showing preview only (3,173K chars total). Download the full file or copy to clipboard to get everything.
Repository: ithewei/libhv
Branch: master
Commit: 62cd137f50d1
Files: 371
Total size: 3.0 MB
Directory structure:
gitextract_3mi7bcus/
├── .bazelrc
├── .clang-format
├── .gitattributes
├── .github/
│ └── workflows/
│ ├── CI.yml
│ └── benchmark.yml
├── .gitignore
├── .travis.yml
├── BUILD.bazel
├── BUILD.md
├── CMakeLists.txt
├── LICENSE
├── Makefile
├── Makefile.in
├── Makefile.vars
├── README-CN.md
├── README.md
├── TREE.md
├── WORKSPACE.bazel
├── base/
│ ├── README.md
│ ├── array.h
│ ├── hatomic.h
│ ├── hbase.c
│ ├── hbase.h
│ ├── hbuf.h
│ ├── hdef.h
│ ├── heap.h
│ ├── hendian.h
│ ├── herr.c
│ ├── herr.h
│ ├── hlog.c
│ ├── hlog.h
│ ├── hmain.c
│ ├── hmain.h
│ ├── hmath.h
│ ├── hmutex.h
│ ├── hplatform.h
│ ├── hproc.h
│ ├── hsocket.c
│ ├── hsocket.h
│ ├── hsysinfo.h
│ ├── hthread.h
│ ├── htime.c
│ ├── htime.h
│ ├── hversion.c
│ ├── hversion.h
│ ├── list.h
│ ├── netinet.h
│ ├── queue.h
│ ├── rbtree.c
│ └── rbtree.h
├── cert/
│ ├── cacert.pem
│ ├── gen.sh
│ ├── server.crt
│ └── server.key
├── cmake/
│ ├── ios.toolchain.cmake
│ ├── libhvConfig.cmake
│ ├── utils.cmake
│ └── vars.cmake
├── config.ini
├── configure
├── cpputil/
│ ├── LRUCache.h
│ ├── RAII.cpp
│ ├── README.md
│ ├── ThreadLocalStorage.cpp
│ ├── ThreadLocalStorage.h
│ ├── hasync.cpp
│ ├── hasync.h
│ ├── hdir.cpp
│ ├── hdir.h
│ ├── hfile.h
│ ├── hmap.h
│ ├── hobjectpool.h
│ ├── hpath.cpp
│ ├── hpath.h
│ ├── hscope.h
│ ├── hstring.cpp
│ ├── hstring.h
│ ├── hthreadpool.h
│ ├── hurl.cpp
│ ├── hurl.h
│ ├── ifconfig.cpp
│ ├── ifconfig.h
│ ├── iniparser.cpp
│ ├── iniparser.h
│ ├── json.hpp
│ └── singleton.h
├── docs/
│ ├── API.md
│ ├── PLAN.md
│ └── cn/
│ ├── Channel.md
│ ├── EventLoop.md
│ ├── HttpClient.md
│ ├── HttpContext.md
│ ├── HttpMessage.md
│ ├── HttpServer.md
│ ├── README.md
│ ├── TcpClient.md
│ ├── TcpServer.md
│ ├── UdpClient.md
│ ├── UdpServer.md
│ ├── WebSocketClient.md
│ ├── WebSocketServer.md
│ ├── hbase.md
│ ├── hlog.md
│ └── hloop.md
├── echo-servers/
│ ├── asio_echo.cpp
│ ├── benchmark.sh
│ ├── build.sh
│ ├── libev_echo.c
│ ├── libevent_echo.c
│ ├── libhv_echo.c
│ ├── libuv_echo.c
│ ├── muduo_echo.cpp
│ ├── pingpong_client.cpp
│ └── poco_echo.cpp
├── etc/
│ ├── hmain_test.conf
│ ├── httpd.conf
│ └── nginx.conf
├── event/
│ ├── README.md
│ ├── epoll.c
│ ├── evport.c
│ ├── hevent.c
│ ├── hevent.h
│ ├── hloop.c
│ ├── hloop.h
│ ├── io_uring.c
│ ├── iocp.c
│ ├── iowatcher.h
│ ├── kcp/
│ │ ├── LICENSE
│ │ ├── hkcp.c
│ │ ├── hkcp.h
│ │ ├── ikcp.c
│ │ └── ikcp.h
│ ├── kqueue.c
│ ├── nio.c
│ ├── nlog.c
│ ├── nlog.h
│ ├── noevent.c
│ ├── overlapio.c
│ ├── overlapio.h
│ ├── poll.c
│ ├── rudp.c
│ ├── rudp.h
│ ├── select.c
│ ├── unpack.c
│ ├── unpack.h
│ └── wepoll/
│ ├── LICENSE
│ ├── README.md
│ ├── wepoll.c
│ └── wepoll.h
├── evpp/
│ ├── Buffer.h
│ ├── Channel.h
│ ├── Event.h
│ ├── EventLoop.h
│ ├── EventLoopThread.h
│ ├── EventLoopThreadPool.h
│ ├── EventLoopThreadPool_test.cpp
│ ├── EventLoopThread_test.cpp
│ ├── EventLoop_test.cpp
│ ├── README.md
│ ├── Status.h
│ ├── TcpClient.h
│ ├── TcpClientEventLoop_test.cpp
│ ├── TcpClient_test.cpp
│ ├── TcpServer.h
│ ├── TcpServer_test.cpp
│ ├── TimerThread.h
│ ├── TimerThread_test.cpp
│ ├── UdpClient.h
│ ├── UdpClient_test.cpp
│ ├── UdpServer.h
│ ├── UdpServer_test.cpp
│ └── build_test.sh
├── examples/
│ ├── BUILD.bazel
│ ├── CMakeLists.txt
│ ├── README.md
│ ├── consul/
│ │ ├── consul.cpp
│ │ ├── consul.h
│ │ └── main.cpp
│ ├── curl.cpp
│ ├── hloop_test.c
│ ├── hmain_test.cpp
│ ├── htimer_test.c
│ ├── http_client_test.cpp
│ ├── http_server_test.cpp
│ ├── httpd/
│ │ ├── handler.cpp
│ │ ├── handler.h
│ │ ├── httpd.cpp
│ │ ├── router.cpp
│ │ └── router.h
│ ├── jsonrpc/
│ │ ├── cJSON.c
│ │ ├── cJSON.h
│ │ ├── handler.h
│ │ ├── jsonrpc_client.c
│ │ ├── jsonrpc_server.c
│ │ └── router.h
│ ├── kcptun/
│ │ ├── README.md
│ │ ├── client/
│ │ │ └── main.cpp
│ │ ├── server/
│ │ │ └── main.cpp
│ │ └── smux/
│ │ ├── smux.cpp
│ │ └── smux.h
│ ├── mqtt/
│ │ ├── mqtt_client_test.cpp
│ │ ├── mqtt_pub.c
│ │ └── mqtt_sub.c
│ ├── multi-thread/
│ │ ├── multi-acceptor-processes.c
│ │ ├── multi-acceptor-threads.c
│ │ └── one-acceptor-multi-workers.c
│ ├── nc.c
│ ├── nmap/
│ │ ├── main.cpp
│ │ ├── nmap.cpp
│ │ └── nmap.h
│ ├── pipe_test.c
│ ├── protorpc/
│ │ ├── handler/
│ │ │ ├── calc.h
│ │ │ ├── handler.h
│ │ │ └── login.h
│ │ ├── proto/
│ │ │ ├── base.proto
│ │ │ ├── calc.proto
│ │ │ ├── login.proto
│ │ │ └── protoc.sh
│ │ ├── protorpc.c
│ │ ├── protorpc.h
│ │ ├── protorpc_client.cpp
│ │ ├── protorpc_server.cpp
│ │ └── router.h
│ ├── socks5_proxy_server.c
│ ├── tcp_chat_server.c
│ ├── tcp_client_test.c
│ ├── tcp_echo_server.c
│ ├── tcp_proxy_server.c
│ ├── tinyhttpd.c
│ ├── tinyproxyd.c
│ ├── udp_echo_server.c
│ ├── udp_proxy_server.c
│ ├── websocket_client_test.cpp
│ ├── websocket_server_test.cpp
│ ├── wget.cpp
│ └── wrk.cpp
├── getting_started.sh
├── hconfig.h.in
├── hexport.h
├── html/
│ ├── EventSource.html
│ ├── WebSocket.html
│ ├── downloads/
│ │ └── 中文.html
│ ├── error.html
│ ├── index.html
│ └── 中文路径/
│ └── 中文名称.txt
├── http/
│ ├── Http1Parser.cpp
│ ├── Http1Parser.h
│ ├── Http2Parser.cpp
│ ├── Http2Parser.h
│ ├── HttpMessage.cpp
│ ├── HttpMessage.h
│ ├── HttpParser.cpp
│ ├── HttpParser.h
│ ├── README.md
│ ├── WebSocketChannel.cpp
│ ├── WebSocketChannel.h
│ ├── WebSocketParser.cpp
│ ├── WebSocketParser.h
│ ├── client/
│ │ ├── AsyncHttpClient.cpp
│ │ ├── AsyncHttpClient.h
│ │ ├── HttpClient.cpp
│ │ ├── HttpClient.h
│ │ ├── WebSocketClient.cpp
│ │ ├── WebSocketClient.h
│ │ ├── axios.h
│ │ └── requests.h
│ ├── grpcdef.h
│ ├── http2def.h
│ ├── http_content.cpp
│ ├── http_content.h
│ ├── http_parser.c
│ ├── http_parser.h
│ ├── httpdef.c
│ ├── httpdef.h
│ ├── multipart_parser.c
│ ├── multipart_parser.h
│ ├── server/
│ │ ├── FileCache.cpp
│ │ ├── FileCache.h
│ │ ├── HttpContext.h
│ │ ├── HttpHandler.cpp
│ │ ├── HttpHandler.h
│ │ ├── HttpMiddleware.cpp
│ │ ├── HttpMiddleware.h
│ │ ├── HttpResponseWriter.cpp
│ │ ├── HttpResponseWriter.h
│ │ ├── HttpServer.cpp
│ │ ├── HttpServer.h
│ │ ├── HttpService.cpp
│ │ ├── HttpService.h
│ │ ├── WebSocketServer.h
│ │ ├── http_page.cpp
│ │ └── http_page.h
│ ├── websocket_parser.c
│ ├── websocket_parser.h
│ ├── wsdef.c
│ └── wsdef.h
├── hv.h
├── hv.rc.in
├── misc/
│ ├── grpc_server.h
│ └── win32_getopt.h
├── mqtt/
│ ├── mqtt_client.c
│ ├── mqtt_client.h
│ ├── mqtt_protocol.c
│ └── mqtt_protocol.h
├── protocol/
│ ├── README.md
│ ├── dns.c
│ ├── dns.h
│ ├── ftp.c
│ ├── ftp.h
│ ├── icmp.c
│ ├── icmp.h
│ ├── smtp.c
│ └── smtp.h
├── scripts/
│ ├── check.sh
│ ├── cmake_cross_compile.sh
│ ├── consul.py
│ ├── consul_agent.sh
│ ├── coredump.sh
│ ├── create_repo.sh
│ ├── libhv.cmake
│ ├── shini.sh
│ ├── test-coverage.sh
│ ├── toolchain.sh
│ ├── unittest.sh
│ └── websocket_server.py
├── ssl/
│ ├── appletls.c
│ ├── gnutls.c
│ ├── hssl.c
│ ├── hssl.h
│ ├── mbedtls.c
│ ├── nossl.c
│ ├── openssl.c
│ └── wintls.c
├── unittest/
│ ├── CMakeLists.txt
│ ├── base64_test.c
│ ├── connect_test.c
│ ├── date_test.c
│ ├── defer_test.cpp
│ ├── ftp_test.c
│ ├── hatomic_test.c
│ ├── hatomic_test.cpp
│ ├── hbase_test.c
│ ├── hlog_test.c
│ ├── hmutex_test.c
│ ├── hpath_test.cpp
│ ├── hstring_test.cpp
│ ├── hthread_test.cpp
│ ├── hurl_test.cpp
│ ├── ifconfig_test.cpp
│ ├── listdir_test.cpp
│ ├── md5_test.c
│ ├── mkdir_test.c
│ ├── nslookup_test.c
│ ├── objectpool_test.cpp
│ ├── ping_test.c
│ ├── rbtree_test.c
│ ├── rmdir_test.c
│ ├── sendmail_test.c
│ ├── sha1_test.c
│ ├── sizeof_test.cpp
│ ├── socketpair_test.c
│ ├── synchronized_test.cpp
│ ├── threadpool_test.cpp
│ └── webbench.c
└── util/
├── README.md
├── base64.c
├── base64.h
├── md5.c
├── md5.h
├── sha1.c
└── sha1.h
================================================
FILE CONTENTS
================================================
================================================
FILE: .bazelrc
================================================
build --copt=-std=c99
build --cxxopt=-std=c++11
build --define BUILD_SHARED=ON
build --define BUILD_STATIC=ON
build --define BUILD_EXAMPLES=ON
build --define BUILD_UNITTEST=OFF
build --define WITH_PROTOCOL=OFF
build --define WITH_EVPP=ON
build --define WITH_HTTP=ON
build --define WITH_HTTP_SERVER=ON
build --define WITH_HTTP_CLIENT=ON
build --define WITH_MQTT=OFF
build --define ENABLE_UDS=OFF
build --define USE_MULTIMAP=OFF
build --define WITH_CURL=OFF
build --define WITH_NGHTTP2=OFF
build --define WITH_OPENSSL=OFF
build --define WITH_GNUTLS=OFF
build --define WITH_MBEDTLS=OFF
build --define WITH_KCP=OFF
build --define WITH_WEPOLL=ON
build --define ENABLE_WINDUMP=OFF
build --define BUILD_FOR_MT=OFF
================================================
FILE: .clang-format
================================================
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: true
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: true
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: true
BeforeElse: true
IndentBraces: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 160
CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: true
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IncludeCategories:
- Regex: '.*'
Priority: 1
- Regex: '^".*/'
Priority: 2
- Regex: '^<)'
Priority: 3
IncludeIsMainRegex: '$'
IndentCaseLabels: false
IndentWidth: 4
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 4
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: true
SortIncludes: false
SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 4
UseTab: Never
...
================================================
FILE: .gitattributes
================================================
cpputil/json.hpp linguist-vendored
================================================
FILE: .github/workflows/CI.yml
================================================
name: CI
on:
push:
paths-ignore:
- '**.md'
pull_request:
paths-ignore:
- '**.md'
jobs:
build-linux:
name: build-linux
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: build
run: |
sudo apt update
sudo apt install libssl-dev libnghttp2-dev
./configure --with-openssl --with-nghttp2 --with-kcp --with-mqtt
make libhv evpp
- name: test
run: |
make check
make run-unittest
build-windows:
name: build-windows
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- name: build
run: |
mkdir cmake-build-win64
cd cmake-build-win64
cmake .. -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release
cmake --build . --config Release
cd ..
- name: test
run: |
cd cmake-build-win64
start bin/Release/http_server_test
bin/Release/http_client_test
bin/Release/curl -v -X HEAD http://example.com/
bin/Release/curl -v -X HEAD https://example.com/
bin/Release/wrk -c 100 -t 2 -d 10s http://127.0.0.1:8080/ping
build-mac:
name: build-mac
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- name: build
run: |
./configure
make libhv evpp examples unittest
- name: test
run: |
bin/curl -v -X HEAD http://example.com/
bin/curl -v -X HEAD https://example.com/
build-android:
name: build-android
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: build
run: |
mkdir cmake-build-arm64
cd cmake-build-arm64
cmake .. -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK_ROOT/build/cmake/android.toolchain.cmake" -DANDROID_ABI="arm64-v8a" -DANDROID_PLATFORM=android-21
cmake --build . --target hv --config Release
build-ios:
name: build-ios
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- name: build
run: |
mkdir cmake-build-ios
cd cmake-build-ios
cmake .. -G Xcode -DCMAKE_TOOLCHAIN_FILE=../cmake/ios.toolchain.cmake -DPLATFORM=OS64 -DARCHS="arm64" -DDEPLOYMENT_TARGET=9.0
cmake --build . --target hv_static --config Release
================================================
FILE: .github/workflows/benchmark.yml
================================================
name: benchmark
on:
push:
paths-ignore:
- '**.md'
pull_request:
paths-ignore:
- '**.md'
jobs:
benchmark:
name: benchmark
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: prepare
run: |
sudo apt update
sudo apt install libssl-dev
sudo apt install iperf
sudo apt install nginx
- name: make examples
run: |
./configure
make examples
- name: build echo-servers
run: |
bash echo-servers/build.sh
- name: benchmark echo-servers
run: |
bash echo-servers/benchmark.sh
- name: benchmark tcp_proxy_server
run: |
iperf -s -p 5001 > /dev/null &
bin/tcp_proxy_server 1212 127.0.0.1:5001 &
iperf -c 127.0.0.1 -p 5001 -l 8K
iperf -c 127.0.0.1 -p 1212 -l 8K
- name: webbench
run: |
sudo nginx -c /etc/nginx/nginx.conf
sudo cp html/index.html index.html
sudo cp html/index.html /var/www/html/index.html
bin/httpd -c etc/httpd.conf -d
ps aux | grep nginx
ps aux | grep httpd
bin/tinyhttpd 9090 &
echo -e "\n======Test nginx send file==============================="
bin/wrk -c 100 -t 2 -d 10s http://127.0.0.1:80/
echo -e "\n======Test libhv/httpd send file (with FileCache)========"
bin/wrk -c 100 -t 2 -d 10s http://127.0.0.1:8080/
echo -e "\n======Test libhv/tinyhttpd send file (no FileCache)======"
bin/wrk -c 100 -t 2 -d 10s http://127.0.0.1:9090/
echo -e "\n======Test nginx 404 Not Found==========================="
bin/wrk -c 100 -t 2 -d 10s http://127.0.0.1:80/404
echo -e "\n======Test libhv/httpd 404 Not Found====================="
bin/wrk -c 100 -t 2 -d 10s http://127.0.0.1:8080/404
echo -e "\n======Test libhv/tinyhttpd 404 Not found================="
bin/wrk -c 100 -t 2 -d 10s http://127.0.0.1:9090/404
echo -e "\n======Test libhv/httpd /ping============================="
bin/wrk -c 100 -t 2 -d 10s http://127.0.0.1:8080/ping
echo -e "\n======Test libhv/tinyhttpd /ping========================="
bin/wrk -c 100 -t 2 -d 10s http://127.0.0.1:9090/ping
================================================
FILE: .gitignore
================================================
# Bazel
bazel-*
MODULE.bazel
MODULE.bazel.lock
# Compiled Object files
*.o
*.lo
*.slo
*.obj
# Compiled Depfile
*.d
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Compiled Static libraries
*.a
*.la
*.lai
*.lib
# Executables
*.exe
*.out
*.app
# cache
*~
*.bk
*.bak
*.old
*.new
# IDE
.vs
.vscode
.DS_Store
tags
cscope*
.ycm*
# generated
examples/protorpc/generated
# output
*.pid
*.log
*.db
include
lib
bin
tmp
dist
test
*_test
build
build-*
config.mk
hconfig.h
html/uploads
# msvc
*.VC.*
*.vcxproj.*
Debug
Release
# cmake
CMakeFiles
CMakeCache.txt
cmake_install.cmake
_codeql_build_dir/
_codeql_detected_source_root
================================================
FILE: .travis.yml
================================================
language: cpp
jobs:
include:
- os: linux
dist: xenial
compiler: gcc
env: COVERALLS=no
script:
- ./configure
- make libhv examples unittest evpp
- os: osx
compiler: clang
env: COVERALLS=no
script:
- ./configure
- make libhv examples unittest evpp
- os: windows
compiler: msvc
env: COVERALLS=no
script:
- mkdir win64
- cd win64
- cmake .. -G "Visual Studio 15 2017 Win64"
- cmake --build .
before_script:
- if [ "$COVERALLS" = "yes" ]; then
pip install --user cpp-coveralls;
export CC="$CC --coverage" CXX="$CXX --coverage";
fi
after_success:
- if [ "$COVERALLS" = "yes" ]; then
scripts/test-coverage.sh;
coveralls --gcov-options '\-lp' --include base --include event --include http;
fi
================================================
FILE: BUILD.bazel
================================================
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")
config_setting(
name = "ios",
constraint_values = ["@platforms//apple:ios"],
)
config_setting(
name = "msvc",
values = {
"compiler": "msvc-cl",
},
)
config_setting(
name = "debug",
values = {"compilation_mode": "dbg"},
)
config_setting(
name = "release",
values = {"compilation_mode": "opt"},
)
config_setting(
name = "build_shared",
define_values = {"BUILD_SHARED": "ON"},
)
config_setting(
name = "build_static",
define_values = {"BUILD_STATIC": "ON"}
)
config_setting(
name = "build_examples",
define_values = {"BUILD_EXAMPLES": "ON"},
)
config_setting(
name = "build_unittest",
define_values = {"BUILD_UNITTEST": "ON"}
)
config_setting(
name = "with_protocol",
define_values = {"WITH_PROTOCOL": "ON"}
)
config_setting(
name = "with_evpp",
define_values = {
"WITH_EVPP": "ON",
},
visibility = [":__subpackages__"]
)
config_setting(
name = "with_http",
define_values = {
"WITH_EVPP": "ON",
"WITH_HTTP": "ON",
},
visibility = [":__subpackages__"]
)
config_setting(
name = "with_http_server",
define_values = {
"WITH_EVPP": "ON",
"WITH_HTTP": "ON",
"WITH_HTTP_SERVER": "ON",
},
visibility = [":__subpackages__"]
)
config_setting(
name = "with_http_client",
define_values = {
"WITH_EVPP": "ON",
"WITH_HTTP": "ON",
"WITH_HTTP_CLIENT": "ON",
},
visibility = [":__subpackages__"]
)
config_setting(
name = "with_evpp_nghttp2",
define_values = {
"WITH_EVPP": "ON",
"WITH_HTTP": "ON",
"WITH_NGHTTP2": "ON",
}
)
config_setting(
name = "with_mqtt",
define_values = {"WITH_MQTT": "ON"},
visibility = [":__subpackages__"],
)
config_setting(
name = "enable_uds",
define_values = {"ENABLE_UDS": "ON"}
)
config_setting(
name = "use_multimap",
define_values = {"USE_MULTIMAP": "ON"}
)
config_setting(
name = "with_curl",
define_values = {"WITH_CURL": "ON"}
)
config_setting(
name = "with_nghttp2",
define_values = {"WITH_NGHTTP2": "ON"}
)
config_setting(
name = "with_openssl",
define_values = {"WITH_OPENSSL": "ON"}
)
config_setting(
name = "with_gnutls",
define_values = {"WITH_GNUTLS": "ON"}
)
config_setting(
name = "with_mbedtls",
define_values = {"WITH_MBEDTLS": "ON"}
)
config_setting(
name = "with_kcp",
define_values = {"WITH_KCP": "ON"}
)
config_setting(
name = "with_wepoll",
constraint_values = ["@platforms//os:windows"],
define_values = {"WITH_WEPOLL": "ON"}
)
config_setting(
name = "enable_windump",
constraint_values = ["@platforms//os:windows"],
define_values = {"ENABLE_WINDUMP": "ON"}
)
config_setting(
name = "build_for_mt_dbg",
constraint_values = ["@platforms//os:windows"],
define_values = {
"BUILD_FOR_MT": "ON",
"compilation_mode": "dbg"
}
)
config_setting(
name = "build_for_mt_opt",
constraint_values = ["@platforms//os:windows"],
define_values = {
"BUILD_FOR_MT": "ON",
"compilation_mode": "opt"
}
)
genrule(
name = "config",
outs = ["hconfig.h"],
cmd = "($(execpath configure) && cp hconfig.h $@) || exit 1",
tools = ["configure"],
)
HEADERS_DIRS = ["base", "ssl", "event"] + select({
"with_wepoll": ["event/wepoll"],
"//conditions:default": [],
}) + select({
"with_kcp": ["event/kcp"],
"//conditions:default": [],
}) + ["util"] + select({
"with_protocol": ["protocol"],
"//conditions:default": [],
}) + select({
"with_evpp": ["cpputil", "evpp"],
"//conditions:default": [],
}) + select({
"with_http": ["http"],
"//conditions:default": [],
}) + select({
"with_http_server": ["http/server"],
"//conditions:default": [],
}) + select({
"with_http_client": ["http/client"],
"//conditions:default": [],
}) + select({
"with_mqtt": ["mqtt"],
"//conditions:default": [],
})
COPTS = select({
"debug": ["-DDEBUG"],
"release": ["-DNDEBUG"],
"//conditions:default": [],
}) + select({
"enable_uds": ["-DENABLE_UDS"],
"//conditions:default": [],
}) + select({
"use_multimap": ["-DUSE_MULTIMAP"],
"//conditions:default": [],
}) + select({
"with_curl": ["-DWITH_CURL"],
"//conditions:default": [],
}) + select({
"with_nghttp2": ["-DWITH_NGHTTP2"],
"//conditions:default": [],
}) + select({
"with_openssl": ["-DWITH_OPENSSL"],
"//conditions:default": [],
}) + select({
"with_gnutls": ["-DWITH_GNUTLS"],
"//conditions:default": [],
}) + select({
"with_mbedtls": ["-DWITH_MBEDTLS"],
"//conditions:default": [],
}) + select({
"@platforms//os:windows": ["-DWIN32_LEAN_AND_MEAN", "-D_CRT_SECURE_NO_WARNINGS", "-D_WIN32_WINNT=0x0600"],
"//conditions:default": [],
}) + select({
"enable_windump": ["-DENABLE_WINDUMP"],
"//conditions:default": [],
}) + select({
"build_for_mt_dbg": ["/MTd"],
"build_for_mt_opt": ["/MT"],
"//conditions:default": [],
})
LINKOPTS = select({
"msvc": [],
"//conditions:default": ["-pthread"],
}) + select({
"@platforms//os:linux": [
"-lpthread",
"-lm",
"-ldl",
],
"//conditions:default": [],
}) + select({
"@bazel_tools//tools/cpp:gcc": ["-lrt"],
"//conditions:default": [],
})
BASE_HEADERS = [
"base/hplatform.h",
"base/hdef.h",
"base/hatomic.h",
"base/herr.h",
"base/htime.h",
"base/hmath.h",
"base/hbase.h",
"base/hversion.h",
"base/hsysinfo.h",
"base/hproc.h",
"base/hthread.h",
"base/hmutex.h",
"base/hsocket.h",
"base/hlog.h",
"base/hbuf.h",
"base/hmain.h",
"base/hendian.h",
]
SSL_HEADERS = [
"ssl/hssl.h",
]
EVENT_HEADERS = [
"event/hloop.h",
"event/nlog.h",
]
UTIL_HEADERS = [
"util/base64.h",
"util/md5.h",
"util/sha1.h",
]
CPPUTIL_HEADERS = [
"cpputil/hmap.h",
"cpputil/hstring.h",
"cpputil/hfile.h",
"cpputil/hpath.h",
"cpputil/hdir.h",
"cpputil/hurl.h",
"cpputil/hscope.h",
"cpputil/hthreadpool.h",
"cpputil/hasync.h",
"cpputil/hobjectpool.h",
"cpputil/ifconfig.h",
"cpputil/iniparser.h",
"cpputil/json.hpp",
"cpputil/singleton.h",
"cpputil/ThreadLocalStorage.h",
]
EVPP_HEADERS = [
"evpp/Buffer.h",
"evpp/Channel.h",
"evpp/Event.h",
"evpp/EventLoop.h",
"evpp/EventLoopThread.h",
"evpp/EventLoopThreadPool.h",
"evpp/Status.h",
"evpp/TcpClient.h",
"evpp/TcpServer.h",
"evpp/UdpClient.h",
"evpp/UdpServer.h",
]
PROTOCOL_HEADERS = [
"protocol/icmp.h",
"protocol/dns.h",
"protocol/ftp.h",
"protocol/smtp.h",
]
HTTP_HEADERS = [
"http/httpdef.h",
"http/wsdef.h",
"http/http_content.h",
"http/HttpMessage.h",
"http/HttpParser.h",
"http/WebSocketParser.h",
"http/WebSocketChannel.h",
]
HTTP2_HEADERS = [
"http/http2def.h",
"http/grpcdef.h",
]
HTTP_CLIENT_HEADERS = [
"http/client/HttpClient.h",
"http/client/requests.h",
"http/client/axios.h",
"http/client/AsyncHttpClient.h",
"http/client/WebSocketClient.h",
]
HTTP_SERVER_HEADERS = [
"http/server/HttpServer.h",
"http/server/HttpService.h",
"http/server/HttpContext.h",
"http/server/HttpResponseWriter.h",
"http/server/WebSocketServer.h",
]
MQTT_HEADERS = [
"mqtt/mqtt_protocol.h",
"mqtt/mqtt_client.h",
]
HEADERS = ["hv.h", ":config", "hexport.h"] + BASE_HEADERS + SSL_HEADERS + EVENT_HEADERS + UTIL_HEADERS + select({
"with_protocol": PROTOCOL_HEADERS,
"//conditions:default": [],
}) + select({
"with_evpp": CPPUTIL_HEADERS + EVPP_HEADERS,
"//conditions:default": [],
}) + select({
"with_http": HTTP_HEADERS,
"//conditions:default": [],
}) + select({
"with_evpp_nghttp2": HTTP2_HEADERS,
"//conditions:default": [],
}) + select({
"with_http_server": HTTP_SERVER_HEADERS,
"//conditions:default": [],
}) + select({
"with_http_client": HTTP_CLIENT_HEADERS,
"//conditions:default": [],
}) + select({
"with_mqtt": MQTT_HEADERS,
"//conditions:default": [],
})
CORE_SRCS = glob(
["*.h"], exclude = ["*_test.c"]
) + glob(
["base/*.h", "base/*.c", "base/*.cpp"], exclude = ["base/*_test.c"]
) + glob(
["ssl/*.h", "ssl/*.c", "ssl/*.cpp"], exclude = ["ssl/*_test.c"]
) + glob(
["event/*.h", "event/*.c", "event/*.cpp"], exclude = ["event/*_test.c"]
) + select({
"with_wepoll": glob(["event/wepoll/*.h", "event/wepoll/*.c", "event/wepoll/*.cpp"], exclude = ["event/wepoll/*_test.c"]),
"//conditions:default": [],
}) + select({
"with_kcp": glob(["event/kcp/*.h", "event/kcp/*.c", "event/kcp/*.cpp"], exclude = ["event/kcp/*_test.c"]),
"//conditions:default": [],
})
SRCS = CORE_SRCS + glob(["util/*.h", "util/*.c", "util/*.cpp"], exclude = ["util/*_test.c"]) + select({
"with_protocol": glob(["protocol/*.h", "protocol/*.c", "protocol/*.cpp"], exclude = ["protocol/*_test.c"]),
"//conditions:default": [],
}) + select({
"with_evpp": glob(["cpputil/*.h", "cpputil/*.c", "cpputil/*.cpp", "evpp/*.h", "evpp/*.c", "evpp/*.cpp"], exclude = ["cpputil/*_test.c", "evpp/*_test.c", "evpp/*_test.cpp"]),
"//conditions:default": [],
}) + select({
"with_http": glob(["http/*.h", "http/*.c", "http/*.cpp"], exclude = ["http/*_test.c"]),
"//conditions:default": [],
}) + select({
"with_http_server": glob(["http/server/*.h", "http/server/*.c", "http/server/*.cpp"], exclude = ["http/server/*_test.c"]),
"//conditions:default": [],
}) + select({
"with_http_client": glob(["http/client/*.h", "http/client/*.c", "http/client/*.cpp"], exclude = ["http/client/*_test.c"]),
"//conditions:default": [],
}) + select({
"with_mqtt": glob(["mqtt/*.h", "mqtt/*.c", "mqtt/*.cpp"], exclude = ["mqtt/*_test.c"]),
"//conditions:default": [],
})
cc_library(
name = "hv_static",
srcs = SRCS,
hdrs = HEADERS,
includes = HEADERS_DIRS,
defines = ["HV_STATICLIB"],
copts = COPTS,
linkstatic = True,
linkopts = LINKOPTS,
)
cc_library(
name = "hv",
srcs = SRCS,
hdrs = HEADERS,
includes = HEADERS_DIRS,
defines = ["HV_DYNAMICLIB"],
copts = COPTS,
linkopts = LINKOPTS,
visibility = ["//visibility:public"]
)
filegroup(
name = "libhv",
srcs = select({
"build_shared": [":hv"],
"//conditions:default": [],
}) + select({
"build_static": [":hv_static"],
"//conditions:default": [],
}) + select({
"build_examples": ["//examples:examples"],
"//conditions:default": [],
})
)
================================================
FILE: BUILD.md
================================================
## Prequired
- c99
- c++11
gcc4.8+, msvc2015 or later
## Makefile
options see [config.ini](config.ini)
```
./configure --with-openssl
make
sudo make install
```
## cmake
options see [CMakeLists.txt](CMakeLists.txt)
```
mkdir build
cd build
cmake .. -DWITH_OPENSSL=ON
cmake --build .
```
## bazel
options see [.bazelrc](.bazelrc)
```
bazel build libhv
```
## Unix
use Makefile or cmake or bazel
## Windows
use cmake
```
mkdir win64
cd win64
cmake .. -G "Visual Studio 15 2017 Win64"
#cmake .. -G "Visual Studio 16 2019" -A x64
#cmake .. -G "Visual Studio 17 2022" -A x64
cmake --build .
```
## CROSS_COMPILE
use Makefile
```
sudo apt install gcc-arm-linux-gnueabi g++-arm-linux-gnueabi # ubuntu
export CROSS_COMPILE=arm-linux-gnueabi-
./configure
make clean
make libhv
```
or use cmake
```
mkdir build
cd build
cmake .. -DCMAKE_C_COMPILER=arm-linux-gnueabi-gcc -DCMAKE_CXX_COMPILER=arm-linux-gnueabi-g++
cmake --build . --target libhv libhv_static
```
### mingw
see CROSS_COMPILE
```
sudo apt install mingw-w64 # ubuntu
#export CROSS_COMPILE=i686-w64-mingw32-
export CROSS_COMPILE=x86_64-w64-mingw32-
./configure
make clean
make libhv
```
### Android
```
#https://developer.android.com/ndk/downloads
#export ANDROID_NDK_ROOT=~/Downloads/android-ndk-r21b
mkdir build
cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK_ROOT/build/cmake/android.toolchain.cmake" -DANDROID_ABI="arm64-v8a" -DANDROID_PLATFORM=android-21
cmake --build . --target hv --config Release
```
### iOS
```
mkdir build
cd build
cmake .. -G Xcode -DCMAKE_TOOLCHAIN_FILE=../cmake/ios.toolchain.cmake -DPLATFORM=OS64 -DARCHS="arm64" -DDEPLOYMENT_TARGET=9.0
cmake --build . --target hv_static --config Release
```
## targets
### lib
- make libhv
### examples
- make examples
### unittest
- make unittest
## options
### compile without c++
```
./configure --without-evpp
make clean && make libhv
```
### compile WITH_OPENSSL
Enable SSL/TLS in libhv is so easy :)
```
// see ssl/hssl.h
hssl_ctx_t hssl_ctx_new(hssl_ctx_opt_t* opt);
// see event/hloop.h
int hio_new_ssl_ctx(hio_t* io, hssl_ctx_opt_t* opt);
```
https is the best example.
```
sudo apt install openssl libssl-dev # ubuntu
./configure --with-openssl
make clean && make
bin/httpd -s restart -d
bin/curl -v http://localhost:8080
bin/curl -v https://localhost:8443
```
### compile WITH_CURL
```
./configure --with-curl
make clean && make
bin/httpd -s restart -d
bin/curl -v http://localhost:8080
```
### compile WITH_NGHTTP2
```
sudo apt install libnghttp2-dev # ubuntu
./configure --with-nghttp2
make clean && make
bin/httpd -s restart -d
bin/curl -v http://localhost:8080 --http2
```
### compile WITH_KCP
```
./configure --with-kcp
make clean && make
```
### compile WITH_MQTT
```
./configure --with-mqtt
make clean && make
```
### More
```
./configure --help
```
================================================
FILE: CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.6)
cmake_policy(SET CMP0077 NEW)
project(hv VERSION 1.3.4)
option(BUILD_SHARED "build shared library" ON)
option(BUILD_STATIC "build static library" ON)
option(BUILD_EXAMPLES "build examples" ON)
option(BUILD_UNITTEST "build unittest" OFF)
# see config.ini
option(WITH_PROTOCOL "compile protocol" OFF)
option(WITH_EVPP "compile evpp" ON)
option(WITH_HTTP "compile http" ON)
option(WITH_HTTP_SERVER "compile http/server" ON)
option(WITH_HTTP_CLIENT "compile http/client" ON)
option(WITH_MQTT "compile mqtt" OFF)
option(ENABLE_UDS "Unix Domain Socket" OFF)
option(USE_MULTIMAP "MultiMap" OFF)
option(WITH_CURL "with curl library (deprecated)" OFF)
option(WITH_NGHTTP2 "with nghttp2 library" OFF)
option(WITH_OPENSSL "with openssl library" OFF)
option(WITH_GNUTLS "with gnutls library" OFF)
option(WITH_MBEDTLS "with mbedtls library" OFF)
option(WITH_KCP "compile event/kcp" OFF)
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
option(WITH_IO_URING "with io_uring" OFF)
endif()
if(WIN32 OR MINGW)
option(WITH_WEPOLL "compile event/wepoll -> use iocp" ON)
option(ENABLE_WINDUMP "Windows MiniDumpWriteDump" OFF)
option(BUILD_FOR_MT "build for /MT" OFF)
if(BUILD_FOR_MT)
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MTd")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MT")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
endif()
endif()
message(STATUS "CMAKE_SOURCE_DIR=${CMAKE_SOURCE_DIR}")
message(STATUS "CMAKE_CURRENT_SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}")
if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}")
set(BUILD_EXAMPLES OFF)
endif()
if(IOS)
set(BUILD_SHARED OFF)
set(BUILD_EXAMPLES OFF)
endif()
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake;${CMAKE_MODULE_PATH}")
include(utils)
include(vars)
# see configure
# Checks for header files
check_header("stdbool.h")
check_header("stdint.h")
check_header("stdatomic.h")
check_header("sys/types.h")
check_header("sys/stat.h")
check_header("sys/time.h")
check_header("fcntl.h")
check_header("pthread.h")
check_header("endian.h")
check_header("sys/endian.h")
# Checks for functions
if(NOT MSVC)
set(CMAKE_REQUIRED_LIBRARIES "-pthread")
endif()
check_function("gettid" "unistd.h")
check_function("strlcpy" "string.h")
check_function("strlcat" "string.h")
check_function("clock_gettime" "time.h")
check_function("gettimeofday" "sys/time.h")
check_function("pthread_spin_lock" "pthread.h")
check_function("pthread_mutex_timedlock" "pthread.h")
check_function("sem_timedwait" "semaphore.h")
check_function("pipe" "unistd.h")
check_function("socketpair" "sys/socket.h")
check_function("eventfd" "sys/eventfd.h")
check_function("setproctitle" "unistd.h")
if (NOT HAVE_CLOCK_GETTIME)
include(CheckLibraryExists)
check_library_exists(rt clock_gettime "" HAVE_CLOCK_GETTIME_IN_RT)
if (HAVE_CLOCK_GETTIME_IN_RT)
set(HAVE_CLOCK_GETTIME ${HAVE_CLOCK_GETTIME_IN_RT})
endif()
endif()
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/hconfig.h.in ${CMAKE_CURRENT_SOURCE_DIR}/hconfig.h)
# see Makefile.in
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED True)
if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_C_COMPILER_ID STREQUAL "GNU")
set(CMAKE_C_EXTENSIONS ON)
endif()
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(INCDIR include)
set(SRCDIR src)
set(LIBDIR lib)
set(BINDIR bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${LIBDIR})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${LIBDIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${BINDIR})
message(STATUS "CMAKE_LIBRARY_OUTPUT_DIRECTORY=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}")
set(INCDIRS . include 3rd/include)
set(LIBDIRS . lib 3rd/lib)
include_directories(${INCDIRS} ${SRCDIR})
link_directories(${LIBDIRS})
message(STATUS "CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
add_definitions(-DDEBUG)
else()
add_definitions(-DNDEBUG)
endif()
if(ENABLE_UDS)
add_definitions(-DENABLE_UDS)
endif()
if(USE_MULTIMAP)
add_definitions(-DUSE_MULTIMAP)
endif()
if(WITH_CURL)
add_definitions(-DWITH_CURL)
set(LIBS ${LIBS} curl)
if(WIN32 OR MINGW)
set(LIBS ${LIBS} wldap32 advapi32 crypt32)
endif()
endif()
if(WITH_NGHTTP2)
add_definitions(-DWITH_NGHTTP2)
set(LIBS ${LIBS} nghttp2)
endif()
if(WITH_OPENSSL)
add_definitions(-DWITH_OPENSSL)
find_package(OpenSSL)
if(OpenSSL_FOUND)
set(LIBS ${LIBS} OpenSSL::SSL OpenSSL::Crypto)
else()
set(LIBS ${LIBS} ssl crypto)
endif()
endif()
if(WITH_GNUTLS)
add_definitions(-DWITH_GNUTLS)
set(LIBS ${LIBS} gnutls)
endif()
if(WITH_MBEDTLS)
add_definitions(-DWITH_MBEDTLS)
set(LIBS ${LIBS} mbedtls mbedx509 mbedcrypto)
endif()
if(WITH_IO_URING)
if(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")
message(FATAL_ERROR "WITH_IO_URING is only supported on Linux because liburing is Linux-only.")
endif()
set(LIBS ${LIBS} uring)
endif()
if(WIN32 OR MINGW)
add_definitions(-DWIN32_LEAN_AND_MEAN -D_CRT_SECURE_NO_WARNINGS -D_WIN32_WINNT=0x0600)
set(LIBS ${LIBS} secur32 crypt32 winmm iphlpapi ws2_32)
if(ENABLE_WINDUMP)
add_definitions(-DENABLE_WINDUMP)
set(LIBS ${LIBS} dbghelp)
endif()
endif()
if(ANDROID)
set(LIBS ${LIBS} log)
elseif(UNIX AND NOT MINGW)
set(LIBS ${LIBS} pthread m dl)
find_library(RT_LIBRARY rt)
if(RT_LIBRARY)
set(LIBS ${LIBS} rt)
endif()
endif()
if(APPLE)
set(LIBS ${LIBS} "-framework CoreFoundation" "-framework Security")
endif()
# see Makefile
set(ALL_SRCDIRS . base ssl event event/kcp util cpputil evpp protocol http http/client http/server mqtt)
set(CORE_SRCDIRS . base ssl event)
if(WIN32 OR MINGW)
if(WITH_WEPOLL)
set(CORE_SRCDIRS ${CORE_SRCDIRS} event/wepoll)
endif()
endif()
if(WITH_KCP)
set(CORE_SRCDIRS ${CORE_SRCDIRS} event/kcp)
endif()
set(LIBHV_SRCDIRS ${CORE_SRCDIRS} util)
set(LIBHV_HEADERS hv.h hconfig.h hexport.h)
set(LIBHV_HEADERS ${LIBHV_HEADERS} ${BASE_HEADERS} ${SSL_HEADERS} ${EVENT_HEADERS} ${UTIL_HEADERS})
if(WITH_PROTOCOL)
set(LIBHV_HEADERS ${LIBHV_HEADERS} ${PROTOCOL_HEADERS})
set(LIBHV_SRCDIRS ${LIBHV_SRCDIRS} protocol)
endif()
if(WITH_EVPP)
set(LIBHV_HEADERS ${LIBHV_HEADERS} ${CPPUTIL_HEADERS} ${EVPP_HEADERS})
set(LIBHV_SRCDIRS ${LIBHV_SRCDIRS} cpputil evpp)
if(WITH_HTTP)
set(LIBHV_HEADERS ${LIBHV_HEADERS} ${HTTP_HEADERS})
set(LIBHV_SRCDIRS ${LIBHV_SRCDIRS} http)
if(WITH_NGHTTP2)
set(LIBHV_HEADERS ${LIBHV_HEADERS} ${HTTP2_HEADERS})
endif()
if(WITH_HTTP_SERVER)
set(LIBHV_HEADERS ${LIBHV_HEADERS} ${HTTP_SERVER_HEADERS})
set(LIBHV_SRCDIRS ${LIBHV_SRCDIRS} http/server)
endif()
if(WITH_HTTP_CLIENT)
set(LIBHV_HEADERS ${LIBHV_HEADERS} ${HTTP_CLIENT_HEADERS})
set(LIBHV_SRCDIRS ${LIBHV_SRCDIRS} http/client)
endif()
endif()
if(CMAKE_SYSTEM_NAME MATCHES "Linux" AND CMAKE_COMPILER_IS_GNUCC)
set(LIBS ${LIBS} stdc++)
endif()
endif()
if(WITH_MQTT)
set(LIBHV_HEADERS ${LIBHV_HEADERS} ${MQTT_HEADERS})
set(LIBHV_SRCDIRS ${LIBHV_SRCDIRS} mqtt)
endif()
list_source_directories(LIBHV_SRCS ${LIBHV_SRCDIRS})
if(WIN32)
set(CMAKE_RC_FLAGS_DEBUG -D_DEBUG)
configure_file(${PROJECT_SOURCE_DIR}/${PROJECT_NAME}.rc.in ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.rc)
list(APPEND LIBHV_SRCS ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.rc)
endif()
file(INSTALL ${LIBHV_HEADERS} DESTINATION include/hv)
file(INSTALL ${LIBHV_HEADERS} DESTINATION ${PROJECT_SOURCE_DIR}/include/hv)
if(BUILD_SHARED)
add_library(hv SHARED ${LIBHV_SRCS})
target_compile_definitions(hv PRIVATE HV_DYNAMICLIB)
target_include_directories(hv PRIVATE ${LIBHV_SRCDIRS}
INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:include>)
target_link_libraries(hv ${LIBS})
install(TARGETS hv
EXPORT libhvConfig
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin)
add_custom_target(libhv DEPENDS hv)
endif()
if(BUILD_STATIC)
add_library(hv_static STATIC ${LIBHV_SRCS})
target_compile_definitions(hv_static PUBLIC HV_STATICLIB)
target_include_directories(hv_static PRIVATE ${LIBHV_SRCDIRS}
INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:include>)
target_link_libraries(hv_static ${LIBS})
if(NOT (WIN32 AND BUILD_SHARED))
set_target_properties(hv_static PROPERTIES OUTPUT_NAME hv)
endif()
install(TARGETS hv_static
EXPORT libhvConfig
ARCHIVE DESTINATION lib)
add_custom_target(libhv_static DEPENDS hv_static)
endif()
if(WIN32 AND NOT MINGW)
if(BUILD_SHARED)
install(FILES $<TARGET_PDB_FILE:${PROJECT_NAME}> DESTINATION bin OPTIONAL)
endif()
endif()
install(FILES ${LIBHV_HEADERS} DESTINATION include/hv)
install(EXPORT libhvConfig DESTINATION lib/cmake/libhv)
if(BUILD_SHARED)
set(HV_LIBRARIES hv CACHE INTERNAL "link hv libraries")
else()
add_definitions(-DHV_STATICLIB)
set(HV_LIBRARIES hv_static ${LIBS} CACHE INTERNAL "link hv libraries")
endif()
if(BUILD_EXAMPLES)
add_subdirectory(examples)
# for httpd -c etc/httpd.conf
file(INSTALL etc DESTINATION ${CMAKE_BINARY_DIR})
file(INSTALL etc DESTINATION ${CMAKE_BINARY_DIR}/bin)
file(INSTALL etc DESTINATION ${CMAKE_BINARY_DIR}/examples)
endif()
if(BUILD_UNITTEST)
add_subdirectory(unittest)
endif()
# CPack settings
set(CPACK_PACKAGE_NAME "libhv")
set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}")
set(CPACK_PACKAGE_RELEASE 1)
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "A high-performance C/C++ network library")
set(CPACK_PACKAGE_VENDOR "libhv")
set(CPACK_PACKAGE_CONTACT "ithewei <ithewei@163.com>")
set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_HOST_SYSTEM_PROCESSOR}")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
# Specify the package generators
set(CPACK_GENERATOR "TGZ;DEB;RPM")
# Enable CPack debug output
set(CPACK_PACKAGE_DEBUG True)
# https://cmake.org/cmake/help/latest/variable/CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION.html
set(CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION "ON")
include(CPack)
================================================
FILE: LICENSE
================================================
BSD 3-Clause License
Copyright (c) 2020, ithewei
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: Makefile
================================================
include config.mk
include Makefile.vars
MAKEF=$(MAKE) -f Makefile.in
ALL_SRCDIRS=. base ssl event event/kcp util cpputil evpp protocol http http/client http/server mqtt
CORE_SRCDIRS=. base ssl event
ifeq ($(WITH_KCP), yes)
CORE_SRCDIRS += event/kcp
endif
BUILD_SHARED ?= yes
BUILD_STATIC ?= yes
LIBHV_SRCDIRS = $(CORE_SRCDIRS) util
LIBHV_HEADERS = hv.h hconfig.h hexport.h
LIBHV_HEADERS += $(BASE_HEADERS) $(SSL_HEADERS) $(EVENT_HEADERS) $(UTIL_HEADERS)
ifeq ($(WITH_PROTOCOL), yes)
LIBHV_HEADERS += $(PROTOCOL_HEADERS)
LIBHV_SRCDIRS += protocol
endif
ifeq ($(WITH_EVPP), yes)
LIBHV_HEADERS += $(CPPUTIL_HEADERS) $(EVPP_HEADERS)
LIBHV_SRCDIRS += cpputil evpp
ifeq ($(WITH_HTTP), yes)
LIBHV_HEADERS += $(HTTP_HEADERS)
LIBHV_SRCDIRS += http
ifeq ($(WITH_NGHTTP2), yes)
LIBHV_HEADERS += $(HTTP2_HEADERS)
endif
ifeq ($(WITH_HTTP_SERVER), yes)
LIBHV_HEADERS += $(HTTP_SERVER_HEADERS)
LIBHV_SRCDIRS += http/server
endif
ifeq ($(WITH_HTTP_CLIENT), yes)
LIBHV_HEADERS += $(HTTP_CLIENT_HEADERS)
LIBHV_SRCDIRS += http/client
endif
endif
endif
ifeq ($(WITH_MQTT), yes)
LIBHV_HEADERS += $(MQTT_HEADERS)
LIBHV_SRCDIRS += mqtt
endif
default: all
all: libhv examples
@echo "make all done, please enjoy libhv."
EXAMPLES = hmain_test htimer_test hloop_test pipe_test \
nc tinyhttpd tinyproxyd \
tcp_client_test \
tcp_echo_server \
tcp_chat_server \
tcp_proxy_server \
udp_echo_server \
udp_proxy_server \
socks5_proxy_server \
multi-acceptor-processes \
multi-acceptor-threads \
one-acceptor-multi-workers \
jsonrpc
ifeq ($(WITH_EVPP), yes)
EXAMPLES += nmap
ifeq ($(WITH_HTTP), yes)
EXAMPLES += wrk
ifeq ($(WITH_HTTP_SERVER), yes)
EXAMPLES += http_server_test websocket_server_test
endif
ifeq ($(WITH_HTTP_CLIENT), yes)
EXAMPLES += curl wget consul http_client_test websocket_client_test
ifeq ($(WITH_HTTP_SERVER), yes)
EXAMPLES += httpd
endif
endif
endif
endif
ifeq ($(WITH_MQTT), yes)
EXAMPLES += mqtt_sub mqtt_pub mqtt_client_test
endif
examples: $(EXAMPLES)
@echo "make examples done."
clean:
$(MAKEF) clean SRCDIRS="$(ALL_SRCDIRS)"
$(RM) examples/*.o examples/*/*.o
$(RM) include/hv
@echo "make clean done."
prepare:
$(MKDIR) bin
libhv:
$(MKDIR) lib
ifeq ($(BUILD_SHARED), yes)
ifeq ($(BUILD_STATIC), yes)
$(MAKEF) TARGET=$@ TARGET_TYPE="SHARED|STATIC" SRCDIRS="$(LIBHV_SRCDIRS)"
else
$(MAKEF) TARGET=$@ TARGET_TYPE="SHARED" SRCDIRS="$(LIBHV_SRCDIRS)"
endif
else
ifeq ($(BUILD_STATIC), yes)
$(MAKEF) TARGET=$@ TARGET_TYPE="STATIC" SRCDIRS="$(LIBHV_SRCDIRS)"
endif
endif
$(MKDIR) include/hv
$(CP) $(LIBHV_HEADERS) include/hv
@echo "make libhv done."
install:
$(MKDIR) $(INSTALL_INCDIR)
$(MKDIR) $(INSTALL_LIBDIR)
$(CP) include/hv/* $(INSTALL_INCDIR)
$(CP) lib/libhv.* $(INSTALL_LIBDIR)
$(LDCONFIG)
@echo "make install done."
uninstall: clean
$(RM) $(PREFIX)/include/hv
$(RM) $(PREFIX)/lib/libhv.*
@echo "make uninstall done."
hmain_test: prepare
$(MAKEF) TARGET=$@ SRCDIRS=". base cpputil" SRCS="examples/hmain_test.cpp"
htimer_test: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS)" SRCS="examples/htimer_test.c"
hloop_test: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS)" SRCS="examples/hloop_test.c"
pipe_test: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS)" SRCS="examples/pipe_test.c"
tcp_client_test: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS)" SRCS="examples/tcp_client_test.c"
tcp_echo_server: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS)" SRCS="examples/tcp_echo_server.c"
tcp_chat_server: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS)" SRCS="examples/tcp_chat_server.c"
tcp_proxy_server: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS)" SRCS="examples/tcp_proxy_server.c"
udp_echo_server: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS)" SRCS="examples/udp_echo_server.c"
udp_proxy_server: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS)" SRCS="examples/udp_proxy_server.c"
socks5_proxy_server: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS)" SRCS="examples/socks5_proxy_server.c"
multi-acceptor-processes: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS)" SRCS="examples/multi-thread/multi-acceptor-processes.c"
multi-acceptor-threads: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS)" SRCS="examples/multi-thread/multi-acceptor-threads.c"
one-acceptor-multi-workers: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS)" SRCS="examples/multi-thread/one-acceptor-multi-workers.c"
nc: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS)" SRCS="examples/nc.c"
tinyhttpd: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS)" SRCS="examples/tinyhttpd.c"
tinyproxyd: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS)" SRCS="examples/tinyproxyd.c"
nmap: prepare libhv
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS) cpputil examples/nmap" DEFINES="PRINT_DEBUG"
wrk: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS) util cpputil evpp http" SRCS="examples/wrk.cpp"
httpd: prepare
$(RM) examples/httpd/*.o
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS) util cpputil evpp http http/client http/server examples/httpd"
consul: prepare libhv
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS) util cpputil evpp http http/client examples/consul" DEFINES="PRINT_DEBUG"
curl: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS) util cpputil evpp http http/client" SRCS="examples/curl.cpp"
# $(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS) util cpputil evpp http http/client" SRCS="examples/curl.cpp" WITH_CURL=yes
wget: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS) util cpputil evpp http http/client" SRCS="examples/wget.cpp"
http_server_test: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS) util cpputil evpp http http/server" SRCS="examples/http_server_test.cpp"
http_client_test: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS) util cpputil evpp http http/client" SRCS="examples/http_client_test.cpp"
websocket_server_test: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS) util cpputil evpp http http/server" SRCS="examples/websocket_server_test.cpp"
websocket_client_test: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS) util cpputil evpp http http/client" SRCS="examples/websocket_client_test.cpp"
mqtt_sub: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS) mqtt" SRCS="examples/mqtt/mqtt_sub.c"
mqtt_pub: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS) mqtt" SRCS="examples/mqtt/mqtt_pub.c"
mqtt_client_test: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS) mqtt" SRCS="examples/mqtt/mqtt_client_test.cpp"
kcptun: kcptun_client kcptun_server
kcptun_client: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS) examples/kcptun/smux examples/kcptun/client"
kcptun_server: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS) examples/kcptun/smux examples/kcptun/server"
jsonrpc: jsonrpc_client jsonrpc_server
jsonrpc_client: prepare
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS)" SRCS="examples/jsonrpc/jsonrpc_client.c examples/jsonrpc/cJSON.c"
jsonrpc_server: prepare
$(RM) examples/jsonrpc/*.o
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS)" SRCS="examples/jsonrpc/jsonrpc_server.c examples/jsonrpc/cJSON.c"
protorpc: protorpc_client protorpc_server
protorpc_protoc:
bash examples/protorpc/proto/protoc.sh
protorpc_client: prepare protorpc_protoc
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS) cpputil evpp examples/protorpc/generated" \
SRCS="examples/protorpc/protorpc_client.cpp examples/protorpc/protorpc.c" \
LIBS="protobuf"
protorpc_server: prepare protorpc_protoc
$(RM) examples/protorpc/*.o
$(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS) cpputil evpp examples/protorpc/generated" \
SRCS="examples/protorpc/protorpc_server.cpp examples/protorpc/protorpc.c" \
LIBS="protobuf"
unittest: prepare
$(CC) -g -Wall -O0 -std=c99 -I. -Ibase -o bin/rbtree_test unittest/rbtree_test.c base/rbtree.c
$(CC) -g -Wall -O0 -std=c99 -I. -Ibase -o bin/hbase_test unittest/hbase_test.c base/hbase.c
$(CC) -g -Wall -O0 -std=c99 -I. -Ibase -o bin/mkdir_p unittest/mkdir_test.c base/hbase.c
$(CC) -g -Wall -O0 -std=c99 -I. -Ibase -o bin/rmdir_p unittest/rmdir_test.c base/hbase.c
$(CC) -g -Wall -O0 -std=c99 -I. -Ibase -o bin/date unittest/date_test.c base/htime.c
$(CC) -g -Wall -O0 -std=c99 -I. -Ibase -o bin/hlog_test unittest/hlog_test.c base/hlog.c
$(CC) -g -Wall -O0 -std=c99 -I. -Ibase -o bin/hatomic_test unittest/hatomic_test.c -pthread
$(CXX) -g -Wall -O0 -std=c++11 -I. -Ibase -o bin/hatomic_cpp_test unittest/hatomic_test.cpp -pthread
$(CXX) -g -Wall -O0 -std=c++11 -I. -Ibase -o bin/hthread_test unittest/hthread_test.cpp -pthread
$(CC) -g -Wall -O0 -std=c99 -I. -Ibase -o bin/hmutex_test unittest/hmutex_test.c base/htime.c -pthread
$(CC) -g -Wall -O0 -std=c99 -I. -Ibase -o bin/connect_test unittest/connect_test.c base/hsocket.c base/htime.c
$(CC) -g -Wall -O0 -std=c99 -I. -Ibase -o bin/socketpair_test unittest/socketpair_test.c base/hsocket.c base/htime.c
$(CC) -g -Wall -O0 -std=c99 -I. -Iutil -o bin/base64 unittest/base64_test.c util/base64.c
$(CC) -g -Wall -O0 -std=c99 -I. -Iutil -o bin/md5 unittest/md5_test.c util/md5.c
$(CC) -g -Wall -O0 -std=c99 -I. -Iutil -o bin/sha1 unittest/sha1_test.c util/sha1.c
$(CXX) -g -Wall -O0 -std=c++11 -I. -Ibase -Icpputil -o bin/hstring_test unittest/hstring_test.cpp cpputil/hstring.cpp
$(CXX) -g -Wall -O0 -std=c++11 -I. -Ibase -Icpputil -o bin/hpath_test unittest/hpath_test.cpp cpputil/hpath.cpp
$(CXX) -g -Wall -O0 -std=c++11 -I. -Ibase -Icpputil -o bin/hurl_test unittest/hurl_test.cpp cpputil/hurl.cpp base/hbase.c
$(CXX) -g -Wall -O0 -std=c++11 -I. -Ibase -Icpputil -o bin/ls unittest/listdir_test.cpp cpputil/hdir.cpp
$(CXX) -g -Wall -O0 -std=c++11 -I. -Ibase -Icpputil -o bin/ifconfig unittest/ifconfig_test.cpp cpputil/ifconfig.cpp
$(CXX) -g -Wall -O0 -std=c++11 -I. -Ibase -Icpputil -o bin/defer_test unittest/defer_test.cpp
$(CXX) -g -Wall -O0 -std=c++11 -I. -Ibase -Icpputil -o bin/synchronized_test unittest/synchronized_test.cpp -pthread
$(CXX) -g -Wall -O0 -std=c++11 -I. -Ibase -Icpputil -o bin/threadpool_test unittest/threadpool_test.cpp -pthread
$(CXX) -g -Wall -O0 -std=c++11 -I. -Ibase -Icpputil -o bin/objectpool_test unittest/objectpool_test.cpp -pthread
$(CXX) -g -Wall -O0 -std=c++11 -I. -Ibase -Issl -Ievent -Ievpp -Icpputil -Ihttp -Ihttp/client -Ihttp/server -o bin/sizeof_test unittest/sizeof_test.cpp
$(CC) -g -Wall -O0 -std=c99 -I. -Ibase -Iprotocol -o bin/nslookup unittest/nslookup_test.c protocol/dns.c base/hsocket.c base/htime.c
$(CC) -g -Wall -O0 -std=c99 -I. -Ibase -Iprotocol -o bin/ping unittest/ping_test.c protocol/icmp.c base/hsocket.c base/htime.c -DPRINT_DEBUG
$(CC) -g -Wall -O0 -std=c99 -I. -Ibase -Iprotocol -o bin/ftp unittest/ftp_test.c protocol/ftp.c base/hsocket.c base/htime.c
$(CC) -g -Wall -O0 -std=c99 -I. -Ibase -Iprotocol -Iutil -o bin/sendmail unittest/sendmail_test.c protocol/smtp.c base/hsocket.c base/htime.c util/base64.c
run-unittest: unittest
bash scripts/unittest.sh
check: examples
bash scripts/check.sh
evpp: prepare libhv
$(CXX) -g -Wall -O0 -std=c++11 -I. -Ibase -Issl -Ievent -Icpputil -Ievpp -o bin/EventLoop_test evpp/EventLoop_test.cpp -Llib -lhv -pthread
$(CXX) -g -Wall -O0 -std=c++11 -I. -Ibase -Issl -Ievent -Icpputil -Ievpp -o bin/EventLoopThread_test evpp/EventLoopThread_test.cpp -Llib -lhv -pthread
$(CXX) -g -Wall -O0 -std=c++11 -I. -Ibase -Issl -Ievent -Icpputil -Ievpp -o bin/EventLoopThreadPool_test evpp/EventLoopThreadPool_test.cpp -Llib -lhv -pthread
$(CXX) -g -Wall -O0 -std=c++11 -I. -Ibase -Issl -Ievent -Icpputil -Ievpp -o bin/TimerThread_test evpp/TimerThread_test.cpp -Llib -lhv -pthread
$(CXX) -g -Wall -O0 -std=c++11 -I. -Ibase -Issl -Ievent -Icpputil -Ievpp -o bin/TcpServer_test evpp/TcpServer_test.cpp -Llib -lhv -pthread
$(CXX) -g -Wall -O0 -std=c++11 -I. -Ibase -Issl -Ievent -Icpputil -Ievpp -o bin/TcpClient_test evpp/TcpClient_test.cpp -Llib -lhv -pthread
$(CXX) -g -Wall -O0 -std=c++11 -I. -Ibase -Issl -Ievent -Icpputil -Ievpp -o bin/TcpClientEventLoop_test evpp/TcpClientEventLoop_test.cpp -Llib -lhv -pthread
$(CXX) -g -Wall -O0 -std=c++11 -I. -Ibase -Issl -Ievent -Icpputil -Ievpp -o bin/UdpServer_test evpp/UdpServer_test.cpp -Llib -lhv -pthread
$(CXX) -g -Wall -O0 -std=c++11 -I. -Ibase -Issl -Ievent -Icpputil -Ievpp -o bin/UdpClient_test evpp/UdpClient_test.cpp -Llib -lhv -pthread
# UNIX only
webbench: prepare
$(CC) -o bin/webbench unittest/webbench.c
echo-servers:
$(CXX) -g -Wall -std=c++11 -O3 -o bin/pingpong_client echo-servers/pingpong_client.cpp -lhv -pthread
$(CC) -g -Wall -std=c99 -O3 -o bin/libevent_echo echo-servers/libevent_echo.c -levent
$(CC) -g -Wall -std=c99 -O3 -o bin/libev_echo echo-servers/libev_echo.c -lev
$(CC) -g -Wall -std=c99 -O3 -o bin/libuv_echo echo-servers/libuv_echo.c -luv
$(CC) -g -Wall -std=c99 -O3 -o bin/libhv_echo echo-servers/libhv_echo.c -lhv
$(CXX) -g -Wall -std=c++11 -O3 -o bin/asio_echo echo-servers/asio_echo.cpp -lboost_system -pthread
$(CXX) -g -Wall -std=c++11 -O3 -o bin/poco_echo echo-servers/poco_echo.cpp -lPocoNet -lPocoUtil -lPocoFoundation
# $(CXX) -g -Wall -std=c++11 -O3 -o bin/muduo_echo echo-servers/muduo_echo.cpp -lmuduo_net -lmuduo_base -pthread
echo-benchmark: echo-servers
bash echo-servers/benchmark.sh
.PHONY: clean prepare install uninstall libhv examples unittest evpp echo-servers
================================================
FILE: Makefile.in
================================================
#+++++++++++++++++++++++++++++++++configure++++++++++++++++++++++++++++++++++++++++
# OS=Windows,Linux,Android
# ARCH=x86,x86_64,arm,aarch64
# CC = $(CROSS_COMPILE)gcc
# CXX = $(CROSS_COMPILE)g++
# CPPFLAGS += $(addprefix -D, $(DEFINES))
# CPPFLAGS += $(addprefix -I, $(SRCDIRS))
# CPPFLAGS += $(addprefix -I, $(INCDIRS))
# LDFLAGS += $(addprefix -L, $(LIBDIRS))
# LDFLAGS += $(addprefix -l, $(LIBS))
#
# Usage:
# make all \
# TARGET=libxx \
# TARGET_TYPE=SHARED \
# BUILD_TYPE=DEBUG \
# CROSS_COMPILE=arm-linux-androideabi- \
# SRCDIRS="src/base src/event" \
# INCDIRS="src/util" \
# SRCS="src/util/hmain.cpp src/util/iniparser.cpp" \
# DEFINES=USE_OPENCV \
# LIBS="opencv_core opencv_highgui"
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-include config.mk
# VARIABLES
TARGET ?= test
# BUILD_TYPE=DEBUG,RELEASE
BUILD_TYPE ?= RELEASE
# TARGET_TYPE=EXECUTABLE,SHARED,STATIC,SHARED|STATIC
TARGET_TYPE ?= EXECUTABLE
# COMMANDS
ifdef CROSS_COMPILE
CC = $(CROSS_COMPILE)gcc
CXX = $(CROSS_COMPILE)g++
CPP = $(CC) -E
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
STRIP = $(CROSS_COMPILE)strip
endif
MKDIR = -mkdir -p 2>/dev/null
CP = -cp -r 2>/dev/null
RM = -rm -r 2>/dev/null
# PLATFORM: OS, ARCH
CC_VERSION=$(shell $(CC) --version 2>&1 | head -n 1)
TARGET_PLATFORM=$(shell $(CC) -v 2>&1 | grep Target | sed 's/Target: //')
ifneq ($(findstring mingw, $(TARGET_PLATFORM)), )
OS=Windows
endif
ifneq ($(findstring android, $(TARGET_PLATFORM)), )
OS=Android
endif
ifneq ($(findstring darwin, $(TARGET_PLATFORM)), )
OS=Darwin
endif
ifndef OS
OS=Linux
endif
ifndef ARCH
ARCH=$(shell echo $(TARGET_PLATFORM) | awk -F'-' '{print $$1}')
endif
# CFLAGS, CXXFLAGS, ARFLAGS
BUILD_TYPE_UPPER := $(shell echo $(BUILD_TYPE) | tr 'a-z' 'A-Z')
ifeq ($(BUILD_TYPE_UPPER), DEBUG)
DEFAULT_CFLAGS = -g -Wall -O0
else
DEFAULT_CFLAGS += -O2
endif
CFLAGS ?= $(DEFAULT_CFLAGS)
CXXFLAGS ?= $(DEFAULT_CFLAGS)
ifneq ($(OS), Windows)
ifeq ($(findstring -fPIC, $(CFLAGS)), )
override CFLAGS += -fPIC
endif
ifeq ($(findstring -fPIC, $(CXXFLAGS)), )
override CXXFLAGS += -fPIC
endif
endif
ifeq ($(findstring -std, $(CFLAGS)), )
ifeq ($(OS), Linux)
override CFLAGS += -std=gnu99
else
override CFLAGS += -std=c99
endif
endif
ifeq ($(findstring -std, $(CXXFLAGS)), )
override CXXFLAGS += -std=c++11
endif
override CFLAGS += -MMD
override CXXFLAGS += -MMD
ARFLAGS ?= cr
# DIRS
ifeq ($(OS), Linux)
PREFIX ?= /usr/local
else
PREFIX ?= install
endif
INCDIR = include
LIBDIR = lib
SRCDIR = src
BINDIR = bin
DEPDIR = 3rd
CONFDIR = etc
DISTDIR = dist
DOCDIR = docs
SRCDIRS += $(shell find $(SRCDIR) -type d)
override INCDIRS += $(INCDIR) $(DEPDIR) $(DEPDIR)/include
override LIBDIRS += $(LIBDIR) $(DEPDIR)/lib $(DEPDIR)/lib/$(TARGET_PLATFORM)
ALL_SRCS += $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c $(dir)/*.cc $(dir)/*.cpp))
ifeq ($(ALL_SRCS), )
ALL_SRCS = $(wildcard *.c *.cc *.cpp)
endif
override SRCS += $(filter-out %_test.c %_test.cc %_test.cpp, $(ALL_SRCS))
# OBJS += $(patsubst %.c, %.o, $(SRCS))
# OBJS += $(patsubst %.cc, %.o, $(SRCS))
# OBJS += $(patsubst %.cpp, %.o, $(SRCS))
OBJS := $(addsuffix .o, $(basename $(SRCS)))
DEPS := $(OBJS:.o=.d)
INSTALLED_INCS=$(addprefix $(PREFIX)/$(INCDIR)/, $(shell ls $(INCDIR)))
INSTALLED_LIBS=$(addprefix $(PREFIX)/$(LIBDIR)/, $(shell ls $(LIBDIR)))
INSTALLED_BINS=$(addprefix $(PREFIX)/$(BINDIR)/, $(shell ls $(BINDIR)))
# CPPFLAGS
ifeq ($(OS), Windows)
CPPFLAGS += -D_WIN32_WINNT=0x600
ifeq ($(TARGET_TYPE), SHARED)
CPPFLAGS += -DDLL_EXPORTS
endif
endif
ifeq ($(BUILD_TYPE_UPPER), DEBUG)
CPPFLAGS += -DDEBUG
else
CPPFLAGS += -DNDEBUG
endif
ifeq ($(ENABLE_UDS), yes)
CPPFLAGS += -DENABLE_UDS
endif
ifeq ($(USE_MULTIMAP), yes)
CPPFLAGS += -DUSE_MULTIMAP
endif
CPPFLAGS += $(addprefix -D, $(DEFINES))
CPPFLAGS += $(addprefix -I, $(INCDIRS))
CPPFLAGS += $(addprefix -I, $(SRCDIRS))
# LDFLAGS
ifeq ($(OS), Windows)
LDFLAGS += -static-libgcc -static-libstdc++
endif
ifeq ($(WITH_CURL), yes)
CPPFLAGS += -DWITH_CURL
LDFLAGS += -lcurl
ifeq ($(OS), Windows)
LDFLAGS += -lwldap32 -ladvapi32 -lcrypt32
endif
endif
ifeq ($(WITH_NGHTTP2), yes)
CPPFLAGS += -DWITH_NGHTTP2
LDFLAGS += -lnghttp2
endif
ifeq ($(WITH_OPENSSL), yes)
CPPFLAGS += -DWITH_OPENSSL
LDFLAGS += -lssl -lcrypto
else
ifeq ($(WITH_GNUTLS), yes)
CPPFLAGS += -DWITH_GNUTLS
LDFLAGS += -lgnutls
else
ifeq ($(WITH_MBEDTLS), yes)
CPPFLAGS += -DWITH_MBEDTLS
LDFLAGS += -lmbedtls -lmbedx509 -lmbedcrypto
endif
endif
endif
ifeq ($(OS), Linux)
ifeq ($(WITH_IO_URING), yes)
LDFLAGS += -luring
endif
endif
LDFLAGS += $(addprefix -L, $(LIBDIRS))
LDFLAGS += $(addprefix -l, $(LIBS))
ifeq ($(OS), Windows)
LDFLAGS += -lsecur32 -lcrypt32 -lwinmm -liphlpapi -lws2_32
ifeq ($(ENABLE_WINDUMP), yes)
CPPFLAGS += -DENABLE_WINDUMP
LDFLAGS += -ldbghelp
endif
LDFLAGS += -Wl,-Bstatic -lstdc++ -lpthread -lm
else
ifeq ($(filter %.cc %.cpp, $(SRCS)), )
LINK = $(CC)
else
LINK = $(CXX)
LDFLAGS += -lstdc++
endif
ifeq ($(OS), Android)
LDFLAGS += -lm -llog -ldl
else
LDFLAGS += -lpthread -lm -ldl
LINK_RT=$(shell echo "int main(){return 0;}" | $(CC) -x c - -lrt 2>&1)
ifeq ($(LINK_RT), )
LDFLAGS += -lrt
endif
endif
endif
ifeq ($(OS), Darwin)
LDFLAGS += -framework CoreFoundation -framework Security
endif
LINK ?= $(CC)
# info
$(info $(CC_VERSION))
$(info OS = $(OS))
$(info ARCH = $(ARCH))
$(info MAKE = $(MAKE))
$(info CC = $(CC))
$(info CXX = $(CXX))
$(info CFLAGS = $(CFLAGS))
$(info CXXFLAGS = $(CXXFLAGS))
$(info CPPFLAGS = $(CPPFLAGS))
$(info LDFLAGS = $(LDFLAGS))
$(info TARGET = $(TARGET))
$(info TARGET_TYPE = $(TARGET_TYPE))
$(info TARGET_PLATFORM = $(TARGET_PLATFORM))
$(info BUILD_TYPE = $(BUILD_TYPE))
$(info SRCS=$(SRCS))
$(info OBJS=$(OBJS))
# $(info INSTALLED_INCS=$(INSTALLED_INCS))
# $(info INSTALLED_LIBS=$(INSTALLED_LIBS))
# $(info INSTALLED_BINS=$(INSTALLED_BINS))
default: all
all: prepare $(TARGET)
prepare:
$(MKDIR) $(BINDIR) $(LIBDIR)
$(TARGET): $(OBJS)
ifneq ($(findstring SHARED, $(TARGET_TYPE)), )
ifeq ($(OS), Windows)
$(LINK) -shared $^ -o $(LIBDIR)/$@.dll $(LDFLAGS) -Wl,--output-def,$(LIBDIR)/$(@).def
else
ifeq ($(OS), Darwin)
$(LINK) -dynamiclib -install_name @rpath/$@.dylib $^ -o $(LIBDIR)/$@.dylib $(LDFLAGS)
else
$(LINK) -shared $^ -o $(LIBDIR)/$@.so $(LDFLAGS)
endif
endif
endif
ifneq ($(findstring STATIC, $(TARGET_TYPE)), )
$(AR) $(ARFLAGS) $(LIBDIR)/$@.a $^
endif
ifneq ($(findstring EXECUTABLE, $(TARGET_TYPE)), )
ifeq ($(OS), Windows)
$(LINK) $^ -o $(BINDIR)/$@.exe $(LDFLAGS)
else
$(LINK) $^ -o $(BINDIR)/$@ $(LDFLAGS)
endif
endif
clean:
$(RM) $(OBJS) $(DEPS)
#$(RM) $(LIBDIR)
#$(RM) $(BINDIR)
install:
$(CP) $(INCDIR)/* $(PREFIX)/$(INCDIR)/
$(CP) $(LIBDIR)/* $(PREFIX)/$(LIBDIR)/
$(CP) $(BINDIR)/* $(PREFIX)/$(BINDIR)/
$(LDCONFIG)
uninstall:
$(RM) $(INSTALLED_INCS)
$(RM) $(INSTALLED_LIBS)
$(RM) $(INSTALLED_BINS)
dist:
$(MKDIR) $(DISTDIR)
$(CP) $(INCDIR) $(LIBDIR) $(BINDIR) $(CONFDIR) $(DOCDIR) $(DISTDIR)
undist:
$(RM) $(DISTDIR)
-include $(DEPS)
.PHONY: default all prepare clean install uninstall dist undist
================================================
FILE: Makefile.vars
================================================
MKDIR = -mkdir -p 2>/dev/null
CP = -cp -r 2>/dev/null
RM = -rm -r 2>/dev/null
LDCONFIG = -ldconfig 2>/dev/null
PREFIX ?= /usr/local
INSTALL_INCDIR ?= $(PREFIX)/include/hv
INSTALL_LIBDIR ?= $(PREFIX)/lib
BASE_HEADERS = base/hplatform.h\
\
base/hdef.h\
base/hatomic.h\
base/herr.h\
base/htime.h\
base/hmath.h\
base/hbase.h\
base/hversion.h\
base/hsysinfo.h\
base/hproc.h\
base/hthread.h\
base/hmutex.h\
base/hsocket.h\
base/hlog.h\
base/hbuf.h\
base/hmain.h\
base/hendian.h\
SSL_HEADERS = ssl/hssl.h
EVENT_HEADERS = event/hloop.h\
event/nlog.h\
UTIL_HEADERS = util/base64.h\
util/md5.h\
util/sha1.h\
CPPUTIL_HEADERS = cpputil/hmap.h\
cpputil/hstring.h\
cpputil/hfile.h\
cpputil/hpath.h\
cpputil/hdir.h\
cpputil/hurl.h\
cpputil/hscope.h\
cpputil/hthreadpool.h\
cpputil/hasync.h\
cpputil/hobjectpool.h\
cpputil/ifconfig.h\
cpputil/iniparser.h\
cpputil/json.hpp\
cpputil/singleton.h\
cpputil/LRUCache.h\
cpputil/ThreadLocalStorage.h\
EVPP_HEADERS = evpp/Buffer.h\
evpp/Channel.h\
evpp/Event.h\
evpp/EventLoop.h\
evpp/EventLoopThread.h\
evpp/EventLoopThreadPool.h\
evpp/Status.h\
evpp/TcpClient.h\
evpp/TcpServer.h\
evpp/UdpClient.h\
evpp/UdpServer.h\
PROTOCOL_HEADERS = protocol/icmp.h\
protocol/dns.h\
protocol/ftp.h\
protocol/smtp.h
HTTP_HEADERS = http/httpdef.h\
http/wsdef.h\
http/http_content.h\
http/HttpMessage.h\
http/HttpParser.h\
http/WebSocketParser.h\
http/WebSocketChannel.h\
HTTP2_HEADERS = http/http2def.h\
http/grpcdef.h\
HTTP_CLIENT_HEADERS = http/client/HttpClient.h\
http/client/requests.h\
http/client/axios.h\
http/client/AsyncHttpClient.h\
http/client/WebSocketClient.h\
HTTP_SERVER_HEADERS = http/server/HttpServer.h\
http/server/HttpService.h\
http/server/HttpContext.h\
http/server/HttpResponseWriter.h\
http/server/WebSocketServer.h\
MQTT_HEADERS = mqtt/mqtt_protocol.h\
mqtt/mqtt_client.h\
================================================
FILE: README-CN.md
================================================
[English](README.md) | 中文
# libhv
[](https://github.com/ithewei/libhv/actions/workflows/CI.yml?query=branch%3Amaster)
[](https://github.com/ithewei/libhv/actions/workflows/CI.yml?query=branch%3Amaster)
[](https://github.com/ithewei/libhv/actions/workflows/CI.yml?query=branch%3Amaster)
[](https://github.com/ithewei/libhv/actions/workflows/CI.yml?query=branch%3Amaster)
[](https://github.com/ithewei/libhv/actions/workflows/CI.yml?query=branch%3Amaster)
[](https://github.com/ithewei/libhv/actions/workflows/benchmark.yml?query=branch%3Amaster)
<br>
[](https://github.com/ithewei/libhv/releases)
[](https://github.com/ithewei/libhv/stargazers)
[](https://github.com/ithewei/libhv/forks)
[](https://github.com/ithewei/libhv/issues)
[](https://github.com/ithewei/libhv/pulls)
[](https://github.com/ithewei/libhv/contributors)
[](LICENSE)
<br>
[](https://gitee.com/libhv/libhv)
[](https://github.com/oz123/awesome-c)
[](https://github.com/fffaraz/awesome-cpp)
`libhv`是一个类似于`libevent、libev、libuv`的跨平台网络库,提供了更易用的接口和更丰富的协议。
## 📚 中文资料
- **libhv QQ群**: `739352073`,欢迎加群交流
- **libhv 源码剖析**: <https://hewei.blog.csdn.net/article/details/123295998>
- **libhv 接口手册**: <https://hewei.blog.csdn.net/article/details/103976875>
- **libhv 教程目录**: <https://hewei.blog.csdn.net/article/details/113733758>
- [libhv教程01--介绍与体验](https://hewei.blog.csdn.net/article/details/113702536)
- [libhv教程02--编译与安装](https://hewei.blog.csdn.net/article/details/113704737)
- [libhv教程03--链库与使用](https://hewei.blog.csdn.net/article/details/113706378)
- [libhv教程04--编写一个完整的命令行程序](https://hewei.blog.csdn.net/article/details/113719503)
- [libhv教程05--事件循环以及定时器的简单使用](https://hewei.blog.csdn.net/article/details/113724474)
- [libhv教程06--创建一个简单的TCP服务端](https://hewei.blog.csdn.net/article/details/113737580)
- [libhv教程07--创建一个简单的TCP客户端](https://hewei.blog.csdn.net/article/details/113738900)
- [libhv教程08--创建一个简单的UDP服务端](https://hewei.blog.csdn.net/article/details/113871498)
- [libhv教程09--创建一个简单的UDP客户端](https://hewei.blog.csdn.net/article/details/113871724)
- [libhv教程10--创建一个简单的HTTP服务端](https://hewei.blog.csdn.net/article/details/113982999)
- [libhv教程11--创建一个简单的HTTP客户端](https://hewei.blog.csdn.net/article/details/113984302)
- [libhv教程12--创建一个简单的WebSocket服务端](https://hewei.blog.csdn.net/article/details/113985321)
- [libhv教程13--创建一个简单的WebSocket客户端](https://hewei.blog.csdn.net/article/details/113985895)
- [libhv教程14--200行实现一个纯C版jsonrpc框架](https://hewei.blog.csdn.net/article/details/119920540)
- [libhv教程15--200行实现一个C++版protorpc框架](https://hewei.blog.csdn.net/article/details/119966701)
- [libhv教程16--多线程/多进程服务端编程](https://hewei.blog.csdn.net/article/details/120366024)
- [libhv教程17--Qt中使用libhv](https://hewei.blog.csdn.net/article/details/120699890)
- [libhv教程18--动手写一个tinyhttpd](https://hewei.blog.csdn.net/article/details/121706604)
- [libhv教程19--MQTT的实现与使用](https://hewei.blog.csdn.net/article/details/122753665)
## ✨ 特性
- 跨平台(Linux, Windows, macOS, Android, iOS, BSD, Solaris)
- 高性能事件循环(网络IO事件、定时器事件、空闲事件、自定义事件、信号)
- TCP/UDP服务端/客户端/代理
- TCP支持心跳、重连、转发、多线程安全write和close等特性
- 内置常见的拆包模式(固定包长、分界符、头部长度字段)
- 可靠UDP支持: WITH_KCP
- SSL/TLS加密通信(可选WITH_OPENSSL、WITH_GNUTLS、WITH_MBEDTLS)
- HTTP服务端/客户端(支持https http1/x http2 grpc)
- HTTP支持静态文件服务、目录服务、正向/反向代理服务、同步/异步API处理器
- HTTP支持RESTful风格、路由、中间件、keep-alive长连接、chunked分块、SSE等特性
- WebSocket服务端/客户端
- MQTT客户端
## ⌛️ 构建
见[BUILD.md](BUILD.md)
libhv提供了以下构建方式:
1、通过Makefile:
```shell
./configure
make
sudo make install
```
2、通过cmake:
```shell
mkdir build
cd build
cmake ..
cmake --build .
```
3、通过bazel:
```shell
bazel build libhv
```
4、通过vcpkg:
```shell
vcpkg install libhv
```
5、通过xmake:
```shell
xrepo install libhv
```
## ⚡️ 快速入门
### 体验
运行脚本`./getting_started.sh`:
```shell
# 下载编译
git clone https://github.com/ithewei/libhv.git
cd libhv
./configure
make
# 运行httpd服务
bin/httpd -h
bin/httpd -d
#bin/httpd -c etc/httpd.conf -s restart -d
ps aux | grep httpd
# 文件服务
bin/curl -v localhost:8080
# 目录服务
bin/curl -v localhost:8080/downloads/
# API服务
bin/curl -v localhost:8080/ping
bin/curl -v localhost:8080/echo -d "hello,world!"
bin/curl -v localhost:8080/query?page_no=1\&page_size=10
bin/curl -v localhost:8080/kv -H "Content-Type:application/x-www-form-urlencoded" -d 'user=admin&pswd=123456'
bin/curl -v localhost:8080/json -H "Content-Type:application/json" -d '{"user":"admin","pswd":"123456"}'
bin/curl -v localhost:8080/form -F 'user=admin' -F 'pswd=123456'
bin/curl -v localhost:8080/upload -d "@LICENSE"
bin/curl -v localhost:8080/upload -F "file=@LICENSE"
bin/curl -v localhost:8080/test -H "Content-Type:application/x-www-form-urlencoded" -d 'bool=1&int=123&float=3.14&string=hello'
bin/curl -v localhost:8080/test -H "Content-Type:application/json" -d '{"bool":true,"int":123,"float":3.14,"string":"hello"}'
bin/curl -v localhost:8080/test -F 'bool=1' -F 'int=123' -F 'float=3.14' -F 'string=hello'
# RESTful API: /group/:group_name/user/:user_id
bin/curl -v -X DELETE localhost:8080/group/test/user/123
# 压力测试
bin/wrk -c 1000 -d 10 -t 4 http://127.0.0.1:8080/
```
### TCP
#### TCP服务端
**c版本**: [examples/tcp_echo_server.c](examples/tcp_echo_server.c)
**c++版本**: [evpp/TcpServer_test.cpp](evpp/TcpServer_test.cpp)
```c++
#include "TcpServer.h"
using namespace hv;
int main() {
int port = 1234;
TcpServer srv;
int listenfd = srv.createsocket(port);
if (listenfd < 0) {
return -1;
}
printf("server listen on port %d, listenfd=%d ...\n", port, listenfd);
srv.onConnection = [](const SocketChannelPtr& channel) {
std::string peeraddr = channel->peeraddr();
if (channel->isConnected()) {
printf("%s connected! connfd=%d\n", peeraddr.c_str(), channel->fd());
} else {
printf("%s disconnected! connfd=%d\n", peeraddr.c_str(), channel->fd());
}
};
srv.onMessage = [](const SocketChannelPtr& channel, Buffer* buf) {
// echo
channel->write(buf);
};
srv.setThreadNum(4);
srv.start();
// press Enter to stop
while (getchar() != '\n');
return 0;
}
```
**注意**:
以上示例只是简单的`echo`服务,TCP是流式协议,实际应用中请务必添加边界进行拆包。<br>
文本协议建议加上`\0`或者`\r\n`分隔符,可参考 [examples/jsonrpc](examples/jsonrpc);<br>
二进制协议建议加上自定义协议头,通过头部长度字段表明负载长度,可参考 [examples/protorpc](examples/protorpc);<br>
通过`setUnpack`(c接口即`hio_set_unpack`)设置拆包规则,支持固定包长、分隔符、头部长度字段三种常见的拆包方式,<br>
内部根据拆包规则处理粘包与分包,保证`onMessage`回调上来的是完整的一包数据,大大节省了上层处理粘包与分包的成本。<br>
不想自定义协议和拆包组包的可直接使用现成的`HTTP/WebSocket`协议。<br>
<br>
`channel->write`(c接口即`hio_write`)是非阻塞的(事件循环异步编程里所有的一切都要求是非阻塞的),且多线程安全的。<br>
发送大数据时应该做流控,通过`onWriteComplete`监听写完成事件,在可写时再发送下一帧数据。<br>
具体示例代码可参考 [examples/tinyhttpd.c](examples/tinyhttpd.c) 中的 `http_serve_file`。<br>
<br>
`channel->close`(c接口即`hio_close`) 也是多线程安全的,这可以让网络IO事件循环线程里接收数据、拆包组包、反序列化后放入队列,<br>
消费者线程/线程池从队列里取出数据、处理后发送响应和关闭连接,变得更加简单。<br>
#### TCP客户端
**c版本**: [examples/tcp_client_test.c](examples/tcp_client_test.c)
**c++版本**: [evpp/TcpClient_test.cpp](evpp/TcpClient_test.cpp)
```c++
#include <iostream>
#include "TcpClient.h"
using namespace hv;
int main() {
int port = 1234;
TcpClient cli;
int connfd = cli.createsocket(port);
if (connfd < 0) {
return -1;
}
cli.onConnection = [](const SocketChannelPtr& channel) {
std::string peeraddr = channel->peeraddr();
if (channel->isConnected()) {
printf("connected to %s! connfd=%d\n", peeraddr.c_str(), channel->fd());
} else {
printf("disconnected to %s! connfd=%d\n", peeraddr.c_str(), channel->fd());
}
};
cli.onMessage = [](const SocketChannelPtr& channel, Buffer* buf) {
printf("< %.*s\n", (int)buf->size(), (char*)buf->data());
};
cli.start();
std::string str;
while (std::getline(std::cin, str)) {
if (str == "close") {
cli.closesocket();
} else if (str == "start") {
cli.start();
} else if (str == "stop") {
cli.stop();
break;
} else {
if (!cli.isConnected()) break;
cli.send(str);
}
}
return 0;
}
```
### HTTP
#### HTTP服务端
见[examples/http_server_test.cpp](examples/http_server_test.cpp)
**golang gin 风格**
```c++
#include "HttpServer.h"
using namespace hv;
int main() {
HttpService router;
router.GET("/ping", [](HttpRequest* req, HttpResponse* resp) {
return resp->String("pong");
});
router.GET("/data", [](HttpRequest* req, HttpResponse* resp) {
static char data[] = "0123456789";
return resp->Data(data, 10);
});
router.GET("/paths", [&router](HttpRequest* req, HttpResponse* resp) {
return resp->Json(router.Paths());
});
router.GET("/get", [](HttpRequest* req, HttpResponse* resp) {
resp->json["origin"] = req->client_addr.ip;
resp->json["url"] = req->url;
resp->json["args"] = req->query_params;
resp->json["headers"] = req->headers;
return 200;
});
router.POST("/echo", [](const HttpContextPtr& ctx) {
return ctx->send(ctx->body(), ctx->type());
});
HttpServer server(&router);
server.setPort(8080);
server.setThreadNum(4);
server.run();
return 0;
}
```
**注意**:
上面示例直接运行在`main`主线程,`server.run()`会阻塞当前线程运行,所以`router`和`server`对象不会被析构,<br>
如使用`server.start()`内部会另起线程运行,不会阻塞当前线程,但需要注意`router`和`server`的生命周期,<br>
不要定义为局部变量被析构了,可定义为类成员变量或者全局变量,下面的`WebSocket`服务同理。<br>
#### HTTP客户端
见[examples/http_client_test.cpp](examples/http_client_test.cpp)
**python requests 风格**
```c++
#include "requests.h"
int main() {
auto resp = requests::get("http://www.example.com");
if (resp == NULL) {
printf("request failed!\n");
} else {
printf("%s\n", resp->body.c_str());
}
resp = requests::post("127.0.0.1:8080/echo", "hello,world!");
if (resp == NULL) {
printf("request failed!\n");
} else {
printf("%s\n", resp->body.c_str());
}
return 0;
}
```
附HTTP相关接口文档:
- [class HttpMessage](docs/cn/HttpMessage.md)
- [class HttpClient](docs/cn/HttpClient.md)
- [class HttpServer](docs/cn/HttpServer.md)
- [class HttpContext](docs/cn/HttpContext.md)
### WebSocket
#### WebSocket服务端
见[examples/websocket_server_test.cpp](examples/websocket_server_test.cpp)
```c++
#include "WebSocketServer.h"
using namespace hv;
int main(int argc, char** argv) {
WebSocketService ws;
ws.onopen = [](const WebSocketChannelPtr& channel, const HttpRequestPtr& req) {
printf("onopen: GET %s\n", req->Path().c_str());
};
ws.onmessage = [](const WebSocketChannelPtr& channel, const std::string& msg) {
printf("onmessage: %.*s\n", (int)msg.size(), msg.data());
};
ws.onclose = [](const WebSocketChannelPtr& channel) {
printf("onclose\n");
};
WebSocketServer server(&ws);
server.setPort(9999);
server.setThreadNum(4);
server.run();
return 0;
}
```
#### WebSocket客户端
见[examples/websocket_client_test.cpp](examples/websocket_client_test.cpp)
```c++
#include "WebSocketClient.h"
using namespace hv;
int main(int argc, char** argv) {
WebSocketClient ws;
ws.onopen = []() {
printf("onopen\n");
};
ws.onmessage = [](const std::string& msg) {
printf("onmessage: %.*s\n", (int)msg.size(), msg.data());
};
ws.onclose = []() {
printf("onclose\n");
};
// reconnect: 1,2,4,8,10,10,10...
reconn_setting_t reconn;
reconn_setting_init(&reconn);
reconn.min_delay = 1000;
reconn.max_delay = 10000;
reconn.delay_policy = 2;
ws.setReconnect(&reconn);
ws.open("ws://127.0.0.1:9999/test");
std::string str;
while (std::getline(std::cin, str)) {
if (!ws.isConnected()) break;
if (str == "quit") {
ws.close();
break;
}
ws.send(str);
}
return 0;
}
```
## 🍭 更多示例
### c版本
- 事件循环: [examples/hloop_test.c](examples/hloop_test.c)
- 定时器: [examples/htimer_test.c](examples/htimer_test.c)
- pipe示例: [examples/pipe_test.c](examples/pipe_test.c)
- TCP回显服务: [examples/tcp_echo_server.c](examples/tcp_echo_server.c)
- TCP聊天服务: [examples/tcp_chat_server.c](examples/tcp_chat_server.c)
- TCP代理服务: [examples/tcp_proxy_server.c](examples/tcp_proxy_server.c)
- UDP回显服务: [examples/udp_echo_server.c](examples/udp_echo_server.c)
- UDP代理服务: [examples/udp_proxy_server.c](examples/udp_proxy_server.c)
- SOCKS5代理服务: [examples/socks5_proxy_server.c](examples/socks5_proxy_server.c)
- HTTP服务: [examples/tinyhttpd.c](examples/tinyhttpd.c)
- HTTP代理服务: [examples/tinyproxyd.c](examples/tinyproxyd.c)
- jsonRPC示例: [examples/jsonrpc](examples/jsonrpc)
- MQTT示例: [examples/mqtt](examples/mqtt)
- 多accept进程模式: [examples/multi-thread/multi-acceptor-processes.c](examples/multi-thread/multi-acceptor-processes.c)
- 多accept线程模式: [examples/multi-thread/multi-acceptor-threads.c](examples/multi-thread/multi-acceptor-threads.c)
- 一个accept线程+多worker线程: [examples/multi-thread/one-acceptor-multi-workers.c](examples/multi-thread/one-acceptor-multi-workers.c)
### c++版本
- 事件循环: [evpp/EventLoop_test.cpp](evpp/EventLoop_test.cpp)
- 事件循环线程: [evpp/EventLoopThread_test.cpp](evpp/EventLoopThread_test.cpp)
- 事件循环线程池: [evpp/EventLoopThreadPool_test.cpp](evpp/EventLoopThreadPool_test.cpp)
- 定时器: [evpp/TimerThread_test.cpp](evpp/TimerThread_test.cpp)
- TCP服务端: [evpp/TcpServer_test.cpp](evpp/TcpServer_test.cpp)
- TCP客户端: [evpp/TcpClient_test.cpp](evpp/TcpClient_test.cpp)
- UDP服务端: [evpp/UdpServer_test.cpp](evpp/UdpServer_test.cpp)
- UDP客户端: [evpp/UdpClient_test.cpp](evpp/UdpClient_test.cpp)
- HTTP服务端: [examples/http_server_test.cpp](examples/http_server_test.cpp)
- HTTP客户端: [examples/http_client_test.cpp](examples/http_client_test.cpp)
- WebSocket服务端: [examples/websocket_server_test.cpp](examples/websocket_server_test.cpp)
- WebSocket客户端: [examples/websocket_client_test.cpp](examples/websocket_client_test.cpp)
- protobufRPC示例: [examples/protorpc](examples/protorpc)
- Qt中使用libhv示例: [hv-projects/QtDemo](https://github.com/hv-projects/QtDemo)
### 模拟实现著名的命令行工具
- 网络连接工具: [examples/nc](examples/nc.c)
- 网络扫描工具: [examples/nmap](examples/nmap)
- HTTP服务程序: [examples/httpd](examples/httpd)
- HTTP压测工具: [examples/wrk](examples/wrk.cpp)
- URL请求工具: [examples/curl](examples/curl.cpp)
- 文件下载工具: [examples/wget](examples/wget.cpp)
- 服务注册与发现: [examples/consul](examples/consul)
- kcptun隧道: [examples/kcptun](examples/kcptun)
## 🥇 性能测试
### TCP回显服务pingpong测试
```shell
cd echo-servers
./build.sh
./benchmark.sh
```
**吞吐量**:
```shell
libevent running on port 2001
libev running on port 2002
libuv running on port 2003
libhv running on port 2004
asio running on port 2005
poco running on port 2006
==============2001=====================================
[127.0.0.1:2001] 4 threads 1000 connections run 10s
total readcount=1616761 readbytes=1655563264
throughput = 157 MB/s
==============2002=====================================
[127.0.0.1:2002] 4 threads 1000 connections run 10s
total readcount=2153171 readbytes=2204847104
throughput = 210 MB/s
==============2003=====================================
[127.0.0.1:2003] 4 threads 1000 connections run 10s
total readcount=1599727 readbytes=1638120448
throughput = 156 MB/s
==============2004=====================================
[127.0.0.1:2004] 4 threads 1000 connections run 10s
total readcount=2202271 readbytes=2255125504
throughput = 215 MB/s
==============2005=====================================
[127.0.0.1:2005] 4 threads 1000 connections run 10s
total readcount=1354230 readbytes=1386731520
throughput = 132 MB/s
==============2006=====================================
[127.0.0.1:2006] 4 threads 1000 connections run 10s
total readcount=1699652 readbytes=1740443648
throughput = 165 MB/s
```
### TCP代理服务压测
```shell
# sudo apt install iperf
iperf -s -p 5001 > /dev/null &
bin/tcp_proxy_server 1212 127.0.0.1:5001 &
iperf -c 127.0.0.1 -p 5001 -l 8K
iperf -c 127.0.0.1 -p 1212 -l 8K
```
**带宽**:
```shell
------------------------------------------------------------
[ 3] local 127.0.0.1 port 52560 connected with 127.0.0.1 port 5001
[ ID] Interval Transfer Bandwidth
[ 3] 0.0-10.0 sec 20.8 GBytes 17.9 Gbits/sec
------------------------------------------------------------
[ 3] local 127.0.0.1 port 48142 connected with 127.0.0.1 port 1212
[ ID] Interval Transfer Bandwidth
[ 3] 0.0-10.0 sec 11.9 GBytes 10.2 Gbits/sec
```
### HTTP压测
```shell
# sudo apt install wrk
wrk -c 100 -t 4 -d 10s http://127.0.0.1:8080/
# sudo apt install apache2-utils
ab -c 100 -n 100000 http://127.0.0.1:8080/
```
**libhv(port:8080) vs nginx(port:80)**

以上测试结果可以在 [Github Actions](https://github.com/ithewei/libhv/actions/workflows/benchmark.yml) 中查看。
## 💎 用户案例
如果您在使用`libhv`,欢迎通过PR将信息提交至此列表,让更多的用户了解`libhv`的实际使用场景,以建立更好的网络生态。
| 用户 (公司名/项目名/个人联系方式) | 案例 (项目简介/业务场景) |
| :--- | :--- |
| [阅面科技](https://www.readsense.cn) | [猎户AIoT平台](https://orionweb.readsense.cn)设备管理、人脸检测HTTP服务、人脸搜索HTTP服务 |
| [socks5-libhv](https://gitee.com/billykang/socks5-libhv) | socks5代理 |
| [hvloop](https://github.com/xiispace/hvloop) | 类似[uvloop](https://github.com/MagicStack/uvloop)的python异步IO事件循环 |
| [tsproxyd-android](https://github.com/Haiwen-GitHub/tsproxyd-android) | 一个基于libhv实现的android端web代理服务 |
| [玄舟智维](https://zjzwxw.com) | C100K设备连接网关服务 |
================================================
FILE: README.md
================================================
English | [中文](README-CN.md)
# libhv
[](https://github.com/ithewei/libhv/actions/workflows/CI.yml?query=branch%3Amaster)
[](https://github.com/ithewei/libhv/actions/workflows/CI.yml?query=branch%3Amaster)
[](https://github.com/ithewei/libhv/actions/workflows/CI.yml?query=branch%3Amaster)
[](https://github.com/ithewei/libhv/actions/workflows/CI.yml?query=branch%3Amaster)
[](https://github.com/ithewei/libhv/actions/workflows/CI.yml?query=branch%3Amaster)
[](https://github.com/ithewei/libhv/actions/workflows/benchmark.yml?query=branch%3Amaster)
<br>
[](https://github.com/ithewei/libhv/releases)
[](https://github.com/ithewei/libhv/stargazers)
[](https://github.com/ithewei/libhv/forks)
[](https://github.com/ithewei/libhv/issues)
[](https://github.com/ithewei/libhv/pulls)
[](https://github.com/ithewei/libhv/contributors)
[](LICENSE)
<br>
[](https://gitee.com/libhv/libhv)
[](https://github.com/oz123/awesome-c)
[](https://github.com/fffaraz/awesome-cpp)
Like `libevent, libev, and libuv`,
`libhv` provides event-loop with non-blocking IO and timer,
but simpler api and richer protocols.
## ✨ Features
- Cross-platform (Linux, Windows, macOS, Android, iOS, BSD, Solaris)
- High-performance EventLoop (IO, timer, idle, custom, signal)
- TCP/UDP client/server/proxy
- TCP supports heartbeat, reconnect, upstream, MultiThread-safe write and close, etc.
- Built-in common unpacking modes (FixedLength, Delimiter, LengthField)
- RUDP support: WITH_KCP
- SSL/TLS support: (via WITH_OPENSSL or WITH_GNUTLS or WITH_MBEDTLS)
- HTTP client/server (support https http1/x http2 grpc)
- HTTP supports static service, indexof service, forward/reverse proxy service, sync/async API handler
- HTTP supports RESTful, router, middleware, keep-alive, chunked, SSE, etc.
- WebSocket client/server
- MQTT client
## ⌛️ Build
see [BUILD.md](BUILD.md)
Makefile:
```shell
./configure
make
sudo make install
```
or cmake:
```shell
mkdir build
cd build
cmake ..
cmake --build .
```
or bazel:
```shell
bazel build libhv
```
or vcpkg:
```shell
vcpkg install libhv
```
or xmake:
```shell
xrepo install libhv
```
## ⚡️ Getting Started
run `./getting_started.sh`:
```shell
git clone https://github.com/ithewei/libhv.git
cd libhv
./configure
make
bin/httpd -h
bin/httpd -d
#bin/httpd -c etc/httpd.conf -s restart -d
ps aux | grep httpd
# http file service
bin/curl -v localhost:8080
# http indexof service
bin/curl -v localhost:8080/downloads/
# http api service
bin/curl -v localhost:8080/ping
bin/curl -v localhost:8080/echo -d "hello,world!"
bin/curl -v localhost:8080/query?page_no=1\&page_size=10
bin/curl -v localhost:8080/kv -H "Content-Type:application/x-www-form-urlencoded" -d 'user=admin&pswd=123456'
bin/curl -v localhost:8080/json -H "Content-Type:application/json" -d '{"user":"admin","pswd":"123456"}'
bin/curl -v localhost:8080/form -F 'user=admin' -F 'pswd=123456'
bin/curl -v localhost:8080/upload -d "@LICENSE"
bin/curl -v localhost:8080/upload -F "file=@LICENSE"
bin/curl -v localhost:8080/test -H "Content-Type:application/x-www-form-urlencoded" -d 'bool=1&int=123&float=3.14&string=hello'
bin/curl -v localhost:8080/test -H "Content-Type:application/json" -d '{"bool":true,"int":123,"float":3.14,"string":"hello"}'
bin/curl -v localhost:8080/test -F 'bool=1' -F 'int=123' -F 'float=3.14' -F 'string=hello'
# RESTful API: /group/:group_name/user/:user_id
bin/curl -v -X DELETE localhost:8080/group/test/user/123
# benchmark
bin/wrk -c 1000 -d 10 -t 4 http://127.0.0.1:8080/
```
### TCP
#### tcp server
**c version**: [examples/tcp_echo_server.c](examples/tcp_echo_server.c)
**c++ version**: [evpp/TcpServer_test.cpp](evpp/TcpServer_test.cpp)
```c++
#include "TcpServer.h"
using namespace hv;
int main() {
int port = 1234;
TcpServer srv;
int listenfd = srv.createsocket(port);
if (listenfd < 0) {
return -1;
}
printf("server listen on port %d, listenfd=%d ...\n", port, listenfd);
srv.onConnection = [](const SocketChannelPtr& channel) {
std::string peeraddr = channel->peeraddr();
if (channel->isConnected()) {
printf("%s connected! connfd=%d\n", peeraddr.c_str(), channel->fd());
} else {
printf("%s disconnected! connfd=%d\n", peeraddr.c_str(), channel->fd());
}
};
srv.onMessage = [](const SocketChannelPtr& channel, Buffer* buf) {
// echo
channel->write(buf);
};
srv.setThreadNum(4);
srv.start();
// press Enter to stop
while (getchar() != '\n');
return 0;
}
```
#### tcp client
**c version**: [examples/tcp_client_test.c](examples/tcp_client_test.c)
**c++ version**: [evpp/TcpClient_test.cpp](evpp/TcpClient_test.cpp)
```c++
#include <iostream>
#include "TcpClient.h"
using namespace hv;
int main() {
int port = 1234;
TcpClient cli;
int connfd = cli.createsocket(port);
if (connfd < 0) {
return -1;
}
cli.onConnection = [](const SocketChannelPtr& channel) {
std::string peeraddr = channel->peeraddr();
if (channel->isConnected()) {
printf("connected to %s! connfd=%d\n", peeraddr.c_str(), channel->fd());
} else {
printf("disconnected to %s! connfd=%d\n", peeraddr.c_str(), channel->fd());
}
};
cli.onMessage = [](const SocketChannelPtr& channel, Buffer* buf) {
printf("< %.*s\n", (int)buf->size(), (char*)buf->data());
};
cli.start();
std::string str;
while (std::getline(std::cin, str)) {
if (str == "close") {
cli.closesocket();
} else if (str == "start") {
cli.start();
} else if (str == "stop") {
cli.stop();
break;
} else {
if (!cli.isConnected()) break;
cli.send(str);
}
}
return 0;
}
```
### HTTP
#### http server
see [examples/http_server_test.cpp](examples/http_server_test.cpp)
**golang gin style**
```c++
#include "HttpServer.h"
using namespace hv;
int main() {
HttpService router;
router.GET("/ping", [](HttpRequest* req, HttpResponse* resp) {
return resp->String("pong");
});
router.GET("/data", [](HttpRequest* req, HttpResponse* resp) {
static char data[] = "0123456789";
return resp->Data(data, 10);
});
router.GET("/paths", [&router](HttpRequest* req, HttpResponse* resp) {
return resp->Json(router.Paths());
});
router.GET("/get", [](HttpRequest* req, HttpResponse* resp) {
resp->json["origin"] = req->client_addr.ip;
resp->json["url"] = req->url;
resp->json["args"] = req->query_params;
resp->json["headers"] = req->headers;
return 200;
});
router.POST("/echo", [](const HttpContextPtr& ctx) {
return ctx->send(ctx->body(), ctx->type());
});
HttpServer server(&router);
server.setPort(8080);
server.setThreadNum(4);
server.run();
return 0;
}
```
#### http client
see [examples/http_client_test.cpp](examples/http_client_test.cpp)
**python requests style**
```c++
#include "requests.h"
int main() {
auto resp = requests::get("http://www.example.com");
if (resp == NULL) {
printf("request failed!\n");
} else {
printf("%s\n", resp->body.c_str());
}
resp = requests::post("127.0.0.1:8080/echo", "hello,world!");
if (resp == NULL) {
printf("request failed!\n");
} else {
printf("%s\n", resp->body.c_str());
}
return 0;
}
```
### WebSocket
#### WebSocket server
see [examples/websocket_server_test.cpp](examples/websocket_server_test.cpp)
```c++
#include "WebSocketServer.h"
using namespace hv;
int main(int argc, char** argv) {
WebSocketService ws;
ws.onopen = [](const WebSocketChannelPtr& channel, const HttpRequestPtr& req) {
printf("onopen: GET %s\n", req->Path().c_str());
};
ws.onmessage = [](const WebSocketChannelPtr& channel, const std::string& msg) {
printf("onmessage: %.*s\n", (int)msg.size(), msg.data());
};
ws.onclose = [](const WebSocketChannelPtr& channel) {
printf("onclose\n");
};
WebSocketServer server(&ws);
server.setPort(9999);
server.setThreadNum(4);
server.run();
return 0;
}
```
#### WebSocket client
see [examples/websocket_client_test.cpp](examples/websocket_client_test.cpp)
```c++
#include "WebSocketClient.h"
using namespace hv;
int main(int argc, char** argv) {
WebSocketClient ws;
ws.onopen = []() {
printf("onopen\n");
};
ws.onmessage = [](const std::string& msg) {
printf("onmessage: %.*s\n", (int)msg.size(), msg.data());
};
ws.onclose = []() {
printf("onclose\n");
};
// reconnect: 1,2,4,8,10,10,10...
reconn_setting_t reconn;
reconn_setting_init(&reconn);
reconn.min_delay = 1000;
reconn.max_delay = 10000;
reconn.delay_policy = 2;
ws.setReconnect(&reconn);
ws.open("ws://127.0.0.1:9999/test");
std::string str;
while (std::getline(std::cin, str)) {
if (!ws.isConnected()) break;
if (str == "quit") {
ws.close();
break;
}
ws.send(str);
}
return 0;
}
```
## 🍭 More examples
### c version
- [examples/hloop_test.c](examples/hloop_test.c)
- [examples/htimer_test.c](examples/htimer_test.c)
- [examples/pipe_test.c](examples/pipe_test.c)
- [examples/tcp_echo_server.c](examples/tcp_echo_server.c)
- [examples/tcp_chat_server.c](examples/tcp_chat_server.c)
- [examples/tcp_proxy_server.c](examples/tcp_proxy_server.c)
- [examples/udp_echo_server.c](examples/udp_echo_server.c)
- [examples/udp_proxy_server.c](examples/udp_proxy_server.c)
- [examples/socks5_proxy_server.c](examples/socks5_proxy_server.c)
- [examples/tinyhttpd.c](examples/tinyhttpd.c)
- [examples/tinyproxyd.c](examples/tinyproxyd.c)
- [examples/jsonrpc](examples/jsonrpc)
- [examples/mqtt](examples/mqtt)
- [examples/multi-thread/multi-acceptor-processes.c](examples/multi-thread/multi-acceptor-processes.c)
- [examples/multi-thread/multi-acceptor-threads.c](examples/multi-thread/multi-acceptor-threads.c)
- [examples/multi-thread/one-acceptor-multi-workers.c](examples/multi-thread/one-acceptor-multi-workers.c)
### c++ version
- [evpp/EventLoop_test.cpp](evpp/EventLoop_test.cpp)
- [evpp/EventLoopThread_test.cpp](evpp/EventLoopThread_test.cpp)
- [evpp/EventLoopThreadPool_test.cpp](evpp/EventLoopThreadPool_test.cpp)
- [evpp/TimerThread_test.cpp](evpp/TimerThread_test.cpp)
- [evpp/TcpServer_test.cpp](evpp/TcpServer_test.cpp)
- [evpp/TcpClient_test.cpp](evpp/TcpClient_test.cpp)
- [evpp/UdpServer_test.cpp](evpp/UdpServer_test.cpp)
- [evpp/UdpClient_test.cpp](evpp/UdpClient_test.cpp)
- [examples/http_server_test.cpp](examples/http_server_test.cpp)
- [examples/http_client_test.cpp](examples/http_client_test.cpp)
- [examples/websocket_server_test.cpp](examples/websocket_server_test.cpp)
- [examples/websocket_client_test.cpp](examples/websocket_client_test.cpp)
- [examples/protorpc](examples/protorpc)
- [hv-projects/QtDemo](https://github.com/hv-projects/QtDemo)
### simulate well-known command line tools
- [examples/nc](examples/nc.c)
- [examples/nmap](examples/nmap)
- [examples/httpd](examples/httpd)
- [examples/wrk](examples/wrk.cpp)
- [examples/curl](examples/curl.cpp)
- [examples/wget](examples/wget.cpp)
- [examples/consul](examples/consul)
- [examples/kcptun](examples/kcptun)
## 🥇 Benchmark
### `pingpong echo-servers`
```shell
cd echo-servers
./build.sh
./benchmark.sh
```
**throughput**:
```shell
libevent running on port 2001
libev running on port 2002
libuv running on port 2003
libhv running on port 2004
asio running on port 2005
poco running on port 2006
==============2001=====================================
[127.0.0.1:2001] 4 threads 1000 connections run 10s
total readcount=1616761 readbytes=1655563264
throughput = 157 MB/s
==============2002=====================================
[127.0.0.1:2002] 4 threads 1000 connections run 10s
total readcount=2153171 readbytes=2204847104
throughput = 210 MB/s
==============2003=====================================
[127.0.0.1:2003] 4 threads 1000 connections run 10s
total readcount=1599727 readbytes=1638120448
throughput = 156 MB/s
==============2004=====================================
[127.0.0.1:2004] 4 threads 1000 connections run 10s
total readcount=2202271 readbytes=2255125504
throughput = 215 MB/s
==============2005=====================================
[127.0.0.1:2005] 4 threads 1000 connections run 10s
total readcount=1354230 readbytes=1386731520
throughput = 132 MB/s
==============2006=====================================
[127.0.0.1:2006] 4 threads 1000 connections run 10s
total readcount=1699652 readbytes=1740443648
throughput = 165 MB/s
```
### `iperf tcp_proxy_server`
```shell
# sudo apt install iperf
iperf -s -p 5001 > /dev/null &
bin/tcp_proxy_server 1212 127.0.0.1:5001 &
iperf -c 127.0.0.1 -p 5001 -l 8K
iperf -c 127.0.0.1 -p 1212 -l 8K
```
**Bandwidth**:
```shell
------------------------------------------------------------
[ 3] local 127.0.0.1 port 52560 connected with 127.0.0.1 port 5001
[ ID] Interval Transfer Bandwidth
[ 3] 0.0-10.0 sec 20.8 GBytes 17.9 Gbits/sec
------------------------------------------------------------
[ 3] local 127.0.0.1 port 48142 connected with 127.0.0.1 port 1212
[ ID] Interval Transfer Bandwidth
[ 3] 0.0-10.0 sec 11.9 GBytes 10.2 Gbits/sec
```
### `webbench`
```shell
# sudo apt install wrk
wrk -c 100 -t 4 -d 10s http://127.0.0.1:8080/
# sudo apt install apache2-utils
ab -c 100 -n 100000 http://127.0.0.1:8080/
```
**libhv(port:8080) vs nginx(port:80)**

Above test results can be found on [Github Actions](https://github.com/ithewei/libhv/actions/workflows/benchmark.yml).
================================================
FILE: TREE.md
================================================
## 目录结构
```
.
├── base libhv基础设施,如常用宏定义、数据结构、日期时间、线程、进程、日志、套接字
├── bin 可执行文件安装目录
├── build cmake默认构建目录
├── cert SSL证书存放目录
├── cmake cmake脚本存放目录
├── cpputil libhv工具类,如字符串、文件、路径、线程池、json解析、ini解析
├── docs 文档存放目录
├── echo-servers 包含libevent、libev、libuv、libhv、asio、poco、muduo等多个网络库的tcp echo server写法,并做压力测试
├── etc 应用程序配置目录
├── event libhv事件循环模块
├── evpp 事件循环c++封装类
├── examples 示例代码
│ └── httpd
├── html 网页document_root目录
│ ├── downloads 下载目录
│ └── uploads 上传目录
├── http libhv http模块
│ ├── client
│ └── server
├── include 头文件安装目录
│ └── hv
├── lib 库文件安装目录
├── logs 日志生成目录
├── misc 杂项
├── mqtt MQTT协议
├── protocol 包含icmp、dns、ftp、smtp等协议的实现
├── scripts shell脚本存放目录
├── ssl SSL/TLS加密通信
├── unittest 单元测试代码
└── util libhv工具函数,如base64、md5、sha1
```
================================================
FILE: WORKSPACE.bazel
================================================
workspace(name = "hv")
================================================
FILE: base/README.md
================================================
## 目录结构
```
.
├── array.h 动态数组
├── hatomic.h 原子操作
├── hbase.h 基础函数
├── hbuf.h 缓存
├── hdef.h 常见宏定义
├── heap.h 堆
├── hendian.h 大小端
├── herr.h 错误码表
├── hlog.h 日志
├── hmain.h 命令行解析
├── hmath.h 数学函数
├── hmutex.h 线程同步锁
├── hplatform.h 平台相关宏
├── hproc.h 进程
├── hsocket.h 套接字
├── hsysinfo.h 系统信息
├── hthread.h 线程
├── htime.h 时间
├── hversion.h 版本
├── list.h 链表
├── queue.h 队列
└── rbtree.h 红黑树
```
================================================
FILE: base/array.h
================================================
#ifndef HV_ARRAY_H_
#define HV_ARRAY_H_
/*
* array
* at: random access by pos
* @effective
* push_back,pop_back,del_nomove,swap
* @ineffective
* add,del
*/
#include <assert.h> // for assert
#include <stddef.h> // for NULL
#include <stdlib.h> // for malloc,realloc,free
#include <string.h> // for memset,memmove
#include "hbase.h" // for HV_ALLOC, HV_FREE
#define ARRAY_INIT_SIZE 16
// #include <vector>
// typedef std::vector<type> atype;
#define ARRAY_DECL(type, atype) \
struct atype { \
type* ptr; \
size_t size; \
size_t maxsize;\
}; \
typedef struct atype atype;\
\
static inline type* atype##_data(atype* p) {\
return p->ptr;\
}\
\
static inline int atype##_size(atype* p) {\
return p->size;\
}\
\
static inline int atype##_maxsize(atype* p) {\
return p->maxsize;\
}\
\
static inline int atype##_empty(atype* p) {\
return p->size == 0;\
}\
\
static inline type* atype##_at(atype* p, int pos) {\
if (pos < 0) {\
pos += p->size;\
}\
assert(pos >= 0 && pos < p->size);\
return p->ptr + pos;\
}\
\
static inline type* atype##_front(atype* p) {\
return p->size == 0 ? NULL : p->ptr;\
}\
\
static inline type* atype##_back(atype* p) {\
return p->size == 0 ? NULL : p->ptr + p->size - 1;\
}\
\
static inline void atype##_init(atype* p, int maxsize) {\
p->size = 0;\
p->maxsize = maxsize;\
HV_ALLOC(p->ptr, sizeof(type) * maxsize);\
}\
\
static inline void atype##_clear(atype* p) {\
p->size = 0;\
memset(p->ptr, 0, sizeof(type) * p->maxsize);\
}\
\
static inline void atype##_cleanup(atype* p) {\
HV_FREE(p->ptr);\
p->size = p->maxsize = 0;\
}\
\
static inline void atype##_resize(atype* p, int maxsize) {\
if (maxsize == 0) maxsize = ARRAY_INIT_SIZE;\
p->ptr = (type*)hv_realloc(p->ptr, sizeof(type) * maxsize, sizeof(type) * p->maxsize);\
p->maxsize = maxsize;\
}\
\
static inline void atype##_double_resize(atype* p) {\
atype##_resize(p, p->maxsize * 2);\
}\
\
static inline void atype##_push_back(atype* p, type* elem) {\
if (p->size == p->maxsize) {\
atype##_double_resize(p);\
}\
p->ptr[p->size] = *elem;\
p->size++;\
}\
\
static inline void atype##_pop_back(atype* p) {\
assert(p->size > 0);\
p->size--;\
}\
\
static inline void atype##_add(atype* p, type* elem, int pos) {\
if (pos < 0) {\
pos += p->size;\
}\
assert(pos >= 0 && pos <= p->size);\
if (p->size == p->maxsize) {\
atype##_double_resize(p);\
}\
if (pos < p->size) {\
memmove(p->ptr + pos+1, p->ptr + pos, sizeof(type) * (p->size - pos));\
}\
p->ptr[pos] = *elem;\
p->size++;\
}\
\
static inline void atype##_del(atype* p, int pos) {\
if (pos < 0) {\
pos += p->size;\
}\
assert(pos >= 0 && pos < p->size);\
p->size--;\
if (pos < p->size) {\
memmove(p->ptr + pos, p->ptr + pos+1, sizeof(type) * (p->size - pos));\
}\
}\
\
static inline void atype##_del_nomove(atype* p, int pos) {\
if (pos < 0) {\
pos += p->size;\
}\
assert(pos >= 0 && pos < p->size);\
p->size--;\
if (pos < p->size) {\
p->ptr[pos] = p->ptr[p->size];\
}\
}\
\
static inline void atype##_swap(atype* p, int pos1, int pos2) {\
if (pos1 < 0) {\
pos1 += p->size;\
}\
if (pos2 < 0) {\
pos2 += p->size;\
}\
type tmp = p->ptr[pos1];\
p->ptr[pos1] = p->ptr[pos2];\
p->ptr[pos2] = tmp;\
}\
#endif // HV_ARRAY_H_
================================================
FILE: base/hatomic.h
================================================
#ifndef HV_ATOMIC_H_
#define HV_ATOMIC_H_
#ifdef __cplusplus
// c++11
#include <atomic>
using std::atomic_flag;
using std::atomic_long;
#define ATOMIC_FLAG_TEST_AND_SET(p) ((p)->test_and_set())
#define ATOMIC_FLAG_CLEAR(p) ((p)->clear())
#else
#include "hplatform.h" // for HAVE_STDATOMIC_H
#if HAVE_STDATOMIC_H
// c11
#include <stdatomic.h>
#define ATOMIC_FLAG_TEST_AND_SET atomic_flag_test_and_set
#define ATOMIC_FLAG_CLEAR atomic_flag_clear
#define ATOMIC_ADD atomic_fetch_add
#define ATOMIC_SUB atomic_fetch_sub
#define ATOMIC_INC(p) ATOMIC_ADD(p, 1)
#define ATOMIC_DEC(p) ATOMIC_SUB(p, 1)
#else
typedef volatile bool atomic_bool;
typedef volatile char atomic_char;
typedef volatile unsigned char atomic_uchar;
typedef volatile short atomic_short;
typedef volatile unsigned short atomic_ushort;
typedef volatile int atomic_int;
typedef volatile unsigned int atomic_uint;
typedef volatile long atomic_long;
typedef volatile unsigned long atomic_ulong;
typedef volatile long long atomic_llong;
typedef volatile unsigned long long atomic_ullong;
typedef volatile size_t atomic_size_t;
typedef struct atomic_flag { atomic_long _Value; } atomic_flag;
#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
#define ATOMIC_FLAG_TEST_AND_SET atomic_flag_test_and_set
static inline bool atomic_flag_test_and_set(atomic_flag* p) {
return !__sync_bool_compare_and_swap(&p->_Value, 0, 1);
}
#define ATOMIC_ADD __sync_fetch_and_add
#define ATOMIC_SUB __sync_fetch_and_sub
#define ATOMIC_INC(p) ATOMIC_ADD(p, 1)
#define ATOMIC_DEC(p) ATOMIC_SUB(p, 1)
#elif defined(_WIN32)
#define ATOMIC_FLAG_TEST_AND_SET atomic_flag_test_and_set
static inline bool atomic_flag_test_and_set(atomic_flag* p) {
// return InterlockedIncrement((LONG*)&p->_Value, 1);
return InterlockedCompareExchange(&p->_Value, 1, 0);
}
#define ATOMIC_ADD InterlockedExchangeAdd
#define ATOMIC_SUB(p, n) InterlockedExchangeAdd(p, -(n))
#define ATOMIC_INC(p) InterlockedExchangeAdd(p, 1)
#define ATOMIC_DEC(p) InterlockedExchangeAdd(p, -1)
#endif
#endif // HAVE_STDATOMIC_H
#endif // __cplusplus
#ifndef ATOMIC_FLAG_INIT
#define ATOMIC_FLAG_INIT { 0 }
#endif
#ifndef ATOMIC_VAR_INIT
#define ATOMIC_VAR_INIT(value) (value)
#endif
#ifndef ATOMIC_FLAG_TEST_AND_SET
#define ATOMIC_FLAG_TEST_AND_SET atomic_flag_test_and_set
static inline bool atomic_flag_test_and_set(atomic_flag* p) {
bool ret = p->_Value;
p->_Value = 1;
return ret;
}
#endif
#ifndef ATOMIC_FLAG_CLEAR
#define ATOMIC_FLAG_CLEAR atomic_flag_clear
static inline void atomic_flag_clear(atomic_flag* p) {
p->_Value = 0;
}
#endif
#ifndef ATOMIC_ADD
#define ATOMIC_ADD(p, n) (*(p) += (n))
#endif
#ifndef ATOMIC_SUB
#define ATOMIC_SUB(p, n) (*(p) -= (n))
#endif
#ifndef ATOMIC_INC
#define ATOMIC_INC(p) ((*(p))++)
#endif
#ifndef ATOMIC_DEC
#define ATOMIC_DEC(p) ((*(p))--)
#endif
typedef atomic_flag hatomic_flag_t;
#define HATOMIC_FLAG_INIT ATOMIC_FLAG_INIT
#define hatomic_flag_test_and_set ATOMIC_FLAG_TEST_AND_SET
#define hatomic_flag_clear ATOMIC_FLAG_CLEAR
typedef atomic_long hatomic_t;
#define HATOMIC_VAR_INIT ATOMIC_VAR_INIT
#define hatomic_add ATOMIC_ADD
#define hatomic_sub ATOMIC_SUB
#define hatomic_inc ATOMIC_INC
#define hatomic_dec ATOMIC_DEC
#endif // HV_ATOMIC_H_
================================================
FILE: base/hbase.c
================================================
#include "hbase.h"
#ifdef OS_DARWIN
#include <mach-o/dyld.h> // for _NSGetExecutablePath
#endif
#include "hatomic.h"
#ifndef RAND_MAX
#define RAND_MAX 2147483647
#endif
static hatomic_t s_alloc_cnt = HATOMIC_VAR_INIT(0);
static hatomic_t s_free_cnt = HATOMIC_VAR_INIT(0);
long hv_alloc_cnt() {
return s_alloc_cnt;
}
long hv_free_cnt() {
return s_free_cnt;
}
void* hv_malloc(size_t size) {
hatomic_inc(&s_alloc_cnt);
void* ptr = malloc(size);
if (!ptr) {
fprintf(stderr, "malloc failed!\n");
exit(-1);
}
return ptr;
}
void* hv_realloc(void* oldptr, size_t newsize, size_t oldsize) {
hatomic_inc(&s_alloc_cnt);
if (oldptr) hatomic_inc(&s_free_cnt);
void* ptr = realloc(oldptr, newsize);
if (!ptr) {
fprintf(stderr, "realloc failed!\n");
exit(-1);
}
if (newsize > oldsize) {
memset((char*)ptr + oldsize, 0, newsize - oldsize);
}
return ptr;
}
void* hv_calloc(size_t nmemb, size_t size) {
hatomic_inc(&s_alloc_cnt);
void* ptr = calloc(nmemb, size);
if (!ptr) {
fprintf(stderr, "calloc failed!\n");
exit(-1);
}
return ptr;
}
void* hv_zalloc(size_t size) {
hatomic_inc(&s_alloc_cnt);
void* ptr = malloc(size);
if (!ptr) {
fprintf(stderr, "malloc failed!\n");
exit(-1);
}
memset(ptr, 0, size);
return ptr;
}
void hv_free(void* ptr) {
if (ptr) {
free(ptr);
ptr = NULL;
hatomic_inc(&s_free_cnt);
}
}
char* hv_strupper(char* str) {
char* p = str;
while (*p != '\0') {
if (*p >= 'a' && *p <= 'z') {
*p &= ~0x20;
}
++p;
}
return str;
}
char* hv_strlower(char* str) {
char* p = str;
while (*p != '\0') {
if (*p >= 'A' && *p <= 'Z') {
*p |= 0x20;
}
++p;
}
return str;
}
char* hv_strreverse(char* str) {
if (str == NULL) return NULL;
char* b = str;
char* e = str;
while(*e) {++e;}
--e;
char tmp;
while (e > b) {
tmp = *e;
*e = *b;
*b = tmp;
--e;
++b;
}
return str;
}
// n = sizeof(dest_buf)
char* hv_strncpy(char* dest, const char* src, size_t n) {
assert(dest != NULL && src != NULL);
char* ret = dest;
while (*src != '\0' && --n > 0) {
*dest++ = *src++;
}
*dest = '\0';
return ret;
}
// n = sizeof(dest_buf)
char* hv_strncat(char* dest, const char* src, size_t n) {
assert(dest != NULL && src != NULL);
char* ret = dest;
while (*dest) {++dest;--n;}
while (*src != '\0' && --n > 0) {
*dest++ = *src++;
}
*dest = '\0';
return ret;
}
bool hv_strstartswith(const char* str, const char* start) {
assert(str != NULL && start != NULL);
while (*str && *start && *str == *start) {
++str;
++start;
}
return *start == '\0';
}
bool hv_strendswith(const char* str, const char* end) {
assert(str != NULL && end != NULL);
int len1 = 0;
int len2 = 0;
while (*str) {++str; ++len1;}
while (*end) {++end; ++len2;}
if (len1 < len2) return false;
while (len2-- > 0) {
--str;
--end;
if (*str != *end) {
return false;
}
}
return true;
}
bool hv_strcontains(const char* str, const char* sub) {
assert(str != NULL && sub != NULL);
return strstr(str, sub) != NULL;
}
bool hv_wildcard_match(const char* str, const char* pattern) {
assert(str != NULL && pattern != NULL);
bool match = false;
while (*str && *pattern) {
if (*pattern == '*') {
match = hv_strendswith(str, pattern + 1);
break;
} else if (*str != *pattern) {
match = false;
break;
} else {
++str;
++pattern;
}
}
return match ? match : (*str == '\0' && *pattern == '\0');
}
char* hv_strnchr(const char* s, char c, size_t n) {
assert(s != NULL);
const char* p = s;
while (*p != '\0' && n-- > 0) {
if (*p == c) return (char*)p;
++p;
}
return NULL;
}
char* hv_strnrchr(const char* s, char c, size_t n) {
assert(s != NULL);
const char* p = s;
const char* last = NULL;
while (*p != '\0' && n-- > 0) {
if (*p == c) last = p;
++p;
}
return (char*)last;
}
char* hv_strrchr_dir(const char* filepath) {
char* p = (char*)filepath;
while (*p) ++p;
while (--p >= filepath) {
#ifdef OS_WIN
if (*p == '/' || *p == '\\')
#else
if (*p == '/')
#endif
return p;
}
return NULL;
}
const char* hv_basename(const char* filepath) {
const char* pos = hv_strrchr_dir(filepath);
return pos ? pos+1 : filepath;
}
const char* hv_suffixname(const char* filename) {
const char* pos = hv_strrchr_dot(filename);
return pos ? pos+1 : "";
}
int hv_mkdir_p(const char* dir) {
if (access(dir, 0) == 0) {
return EEXIST;
}
char tmp[MAX_PATH] = {0};
hv_strncpy(tmp, dir, sizeof(tmp));
char* p = tmp;
char delim = '/';
while (*p) {
#ifdef OS_WIN
if (*p == '/' || *p == '\\') {
delim = *p;
#else
if (*p == '/') {
#endif
*p = '\0';
hv_mkdir(tmp);
*p = delim;
}
++p;
}
if (hv_mkdir(tmp) != 0) {
return EPERM;
}
return 0;
}
int hv_rmdir_p(const char* dir) {
if (access(dir, 0) != 0) {
return ENOENT;
}
if (rmdir(dir) != 0) {
return EPERM;
}
char tmp[MAX_PATH] = {0};
hv_strncpy(tmp, dir, sizeof(tmp));
char* p = tmp;
while (*p) ++p;
while (--p >= tmp) {
#ifdef OS_WIN
if (*p == '/' || *p == '\\') {
#else
if (*p == '/') {
#endif
*p = '\0';
if (rmdir(tmp) != 0) {
return 0;
}
}
}
return 0;
}
bool hv_exists(const char* path) {
return access(path, 0) == 0;
}
bool hv_isdir(const char* path) {
if (access(path, 0) != 0) return false;
struct stat st;
memset(&st, 0, sizeof(st));
stat(path, &st);
return S_ISDIR(st.st_mode);
}
bool hv_isfile(const char* path) {
if (access(path, 0) != 0) return false;
struct stat st;
memset(&st, 0, sizeof(st));
stat(path, &st);
return S_ISREG(st.st_mode);
}
bool hv_islink(const char* path) {
#ifdef OS_WIN
return hv_isdir(path) && (GetFileAttributes(path) & FILE_ATTRIBUTE_REPARSE_POINT);
#else
if (access(path, 0) != 0) return false;
struct stat st;
memset(&st, 0, sizeof(st));
lstat(path, &st);
return S_ISLNK(st.st_mode);
#endif
}
size_t hv_filesize(const char* filepath) {
struct stat st;
memset(&st, 0, sizeof(st));
stat(filepath, &st);
return st.st_size;
}
char* get_executable_path(char* buf, int size) {
#ifdef OS_WIN
GetModuleFileName(NULL, buf, size);
#elif defined(OS_LINUX)
if (readlink("/proc/self/exe", buf, size) == -1) {
return NULL;
}
#elif defined(OS_DARWIN)
_NSGetExecutablePath(buf, (uint32_t*)&size);
#endif
return buf;
}
char* get_executable_dir(char* buf, int size) {
char filepath[MAX_PATH] = {0};
get_executable_path(filepath, sizeof(filepath));
char* pos = hv_strrchr_dir(filepath);
if (pos) {
*pos = '\0';
strncpy(buf, filepath, size);
}
return buf;
}
char* get_executable_file(char* buf, int size) {
char filepath[MAX_PATH] = {0};
get_executable_path(filepath, sizeof(filepath));
char* pos = hv_strrchr_dir(filepath);
if (pos) {
strncpy(buf, pos+1, size);
}
return buf;
}
char* get_run_dir(char* buf, int size) {
return getcwd(buf, size);
}
int hv_rand(int min, int max) {
static int s_seed = 0;
assert(max > min);
if (s_seed == 0) {
s_seed = time(NULL);
srand(s_seed);
}
int _rand = rand();
_rand = min + (int) ((double) ((double) (max) - (min) + 1.0) * ((_rand) / ((RAND_MAX) + 1.0)));
return _rand;
}
char* hv_random_string(char *buf, int len) {
static char s_characters[] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
};
int i = 0;
for (; i < len; i++) {
buf[i] = s_characters[hv_rand(0, sizeof(s_characters) - 1)];
}
buf[i] = '\0';
return buf;
}
bool hv_getboolean(const char* str) {
if (str == NULL) return false;
int len = strlen(str);
if (len == 0) return false;
switch (len) {
case 1: return *str == '1' || *str == 'y' || *str == 'Y';
case 2: return stricmp(str, "on") == 0;
case 3: return stricmp(str, "yes") == 0;
case 4: return stricmp(str, "true") == 0;
case 6: return stricmp(str, "enable") == 0;
default: return false;
}
}
size_t hv_parse_size(const char* str) {
size_t size = 0, n = 0;
const char* p = str;
char c;
while ((c = *p) != '\0') {
if (c >= '0' && c <= '9') {
n = n * 10 + c - '0';
} else {
switch (c) {
case 'K': case 'k': n <<= 10; break;
case 'M': case 'm': n <<= 20; break;
case 'G': case 'g': n <<= 30; break;
case 'T': case 't': if(sizeof(size_t) > 5) n <<= 40; break;
default: break;
}
size += n;
n = 0;
}
++p;
}
return size + n;
}
time_t hv_parse_time(const char* str) {
time_t time = 0, n = 0;
const char* p = str;
char c;
while ((c = *p) != '\0') {
if (c >= '0' && c <= '9') {
n = n * 10 + c - '0';
} else {
switch (c) {
case 's': break;
case 'm': n *= 60; break;
case 'h': n *= 60 * 60; break;
case 'd': n *= 24 * 60 * 60; break;
case 'w': n *= 7 * 24 * 60 * 60; break;
default: break;
}
time += n;
n = 0;
}
++p;
}
return time + n;
}
int hv_parse_url(hurl_t* stURL, const char* strURL) {
if (stURL == NULL || strURL == NULL) return -1;
memset(stURL, 0, sizeof(hurl_t));
const char* begin = strURL;
const char* end = strURL;
while (*end != '\0') ++end;
if (end - begin > 65535) return -2;
// scheme://
const char* sp = strURL;
const char* ep = strstr(sp, "://");
if (ep) {
// stURL->fields[HV_URL_SCHEME].off = sp - begin;
stURL->fields[HV_URL_SCHEME].len = ep - sp;
sp = ep + 3;
}
// user:pswd@host:port
ep = strchr(sp, '/');
if (ep == NULL) ep = end;
const char* user = sp;
const char* host = sp;
const char* pos = hv_strnchr(sp, '@', ep - sp);
if (pos) {
// user:pswd
const char* pswd = hv_strnchr(user, ':', pos - user);
if (pswd) {
stURL->fields[HV_URL_PASSWORD].off = pswd + 1 - begin;
stURL->fields[HV_URL_PASSWORD].len = pos - pswd - 1;
} else {
pswd = pos;
}
stURL->fields[HV_URL_USERNAME].off = user - begin;
stURL->fields[HV_URL_USERNAME].len = pswd - user;
// @
host = pos + 1;
}
// host:port or ipv4:port or [ipv6]:port
const char* hostend = host;
if (*host == '[') {
pos = hv_strnchr(host, ']', ep - host);
if (pos) {
// ipv6
host++;
hostend = pos;
stURL->fields[HV_URL_HOST].off = host - begin;
stURL->fields[HV_URL_HOST].len = hostend - host;
}
}
const char* port = hv_strnchr(hostend, ':', ep - hostend);
if (port) {
stURL->fields[HV_URL_PORT].off = port + 1 - begin;
stURL->fields[HV_URL_PORT].len = ep - port - 1;
// atoi
for (unsigned short i = 1; i <= stURL->fields[HV_URL_PORT].len; ++i) {
stURL->port = stURL->port * 10 + (port[i] - '0');
}
} else {
port = ep;
// set default port
stURL->port = 80;
if (stURL->fields[HV_URL_SCHEME].len > 0) {
if (strncmp(strURL, "https://", 8) == 0) {
stURL->port = 443;
}
}
}
if (stURL->fields[HV_URL_HOST].len == 0) {
stURL->fields[HV_URL_HOST].off = host - begin;
stURL->fields[HV_URL_HOST].len = port - host;
}
if (ep == end) return 0;
// /path
sp = ep;
ep = strchr(sp, '?');
if (ep == NULL) ep = end;
stURL->fields[HV_URL_PATH].off = sp - begin;
stURL->fields[HV_URL_PATH].len = ep - sp;
if (ep == end) return 0;
// ?query
sp = ep + 1;
ep = strchr(sp, '#');
if (ep == NULL) ep = end;
stURL->fields[HV_URL_QUERY].off = sp - begin;
stURL->fields[HV_URL_QUERY].len = ep - sp;
if (ep == end) return 0;
// #fragment
sp = ep + 1;
ep = end;
stURL->fields[HV_URL_FRAGMENT].off = sp - begin;
stURL->fields[HV_URL_FRAGMENT].len = ep - sp;
return 0;
}
================================================
FILE: base/hbase.h
================================================
#ifndef HV_BASE_H_
#define HV_BASE_H_
#include "hexport.h"
#include "hplatform.h" // for bool
#include "hdef.h" // for printd
BEGIN_EXTERN_C
//--------------------alloc/free---------------------------
HV_EXPORT void* hv_malloc(size_t size);
HV_EXPORT void* hv_realloc(void* oldptr, size_t newsize, size_t oldsize);
HV_EXPORT void* hv_calloc(size_t nmemb, size_t size);
HV_EXPORT void* hv_zalloc(size_t size);
HV_EXPORT void hv_free(void* ptr);
#define HV_ALLOC(ptr, size)\
do {\
*(void**)&(ptr) = hv_zalloc(size);\
printd("alloc(%p, size=%llu)\tat [%s:%d:%s]\n", ptr, (unsigned long long)size, __FILE__, __LINE__, __FUNCTION__);\
} while(0)
#define HV_ALLOC_SIZEOF(ptr) HV_ALLOC(ptr, sizeof(*(ptr)))
#define HV_FREE(ptr)\
do {\
if (ptr) {\
hv_free(ptr);\
printd("free( %p )\tat [%s:%d:%s]\n", ptr, __FILE__, __LINE__, __FUNCTION__);\
ptr = NULL;\
}\
} while(0)
#define STACK_OR_HEAP_ALLOC(ptr, size, stack_size)\
unsigned char _stackbuf_[stack_size] = { 0 };\
if ((size) > (stack_size)) {\
HV_ALLOC(ptr, size);\
} else {\
*(unsigned char**)&(ptr) = _stackbuf_;\
}
#define STACK_OR_HEAP_FREE(ptr)\
if ((unsigned char*)(ptr) != _stackbuf_) {\
HV_FREE(ptr);\
}
#define HV_DEFAULT_STACKBUF_SIZE 1024
#define HV_STACK_ALLOC(ptr, size) STACK_OR_HEAP_ALLOC(ptr, size, HV_DEFAULT_STACKBUF_SIZE)
#define HV_STACK_FREE(ptr) STACK_OR_HEAP_FREE(ptr)
HV_EXPORT long hv_alloc_cnt();
HV_EXPORT long hv_free_cnt();
HV_INLINE void hv_memcheck(void) {
printf("Memcheck => alloc:%ld free:%ld\n", hv_alloc_cnt(), hv_free_cnt());
}
#define HV_MEMCHECK atexit(hv_memcheck);
//--------------------string-------------------------------
HV_EXPORT char* hv_strupper(char* str);
HV_EXPORT char* hv_strlower(char* str);
HV_EXPORT char* hv_strreverse(char* str);
HV_EXPORT bool hv_strstartswith(const char* str, const char* start);
HV_EXPORT bool hv_strendswith(const char* str, const char* end);
HV_EXPORT bool hv_strcontains(const char* str, const char* sub);
HV_EXPORT bool hv_wildcard_match(const char* str, const char* pattern);
// strncpy n = sizeof(dest_buf)-1
// hv_strncpy n = sizeof(dest_buf)
HV_EXPORT char* hv_strncpy(char* dest, const char* src, size_t n);
// strncat n = sizeof(dest_buf)-1-strlen(dest)
// hv_strncpy n = sizeof(dest_buf)
HV_EXPORT char* hv_strncat(char* dest, const char* src, size_t n);
#if !HAVE_STRLCPY
#define strlcpy hv_strncpy
#endif
#if !HAVE_STRLCAT
#define strlcat hv_strncat
#endif
HV_EXPORT char* hv_strnchr(const char* s, char c, size_t n);
HV_EXPORT char* hv_strnrchr(const char* s, char c, size_t n);
#define hv_strrchr_dot(str) strrchr(str, '.')
HV_EXPORT char* hv_strrchr_dir(const char* filepath);
// basename
HV_EXPORT const char* hv_basename(const char* filepath);
HV_EXPORT const char* hv_suffixname(const char* filename);
// mkdir -p
HV_EXPORT int hv_mkdir_p(const char* dir);
// rmdir -p
HV_EXPORT int hv_rmdir_p(const char* dir);
// path
HV_EXPORT bool hv_exists(const char* path);
HV_EXPORT bool hv_isdir(const char* path);
HV_EXPORT bool hv_isfile(const char* path);
HV_EXPORT bool hv_islink(const char* path);
HV_EXPORT size_t hv_filesize(const char* filepath);
HV_EXPORT char* get_executable_path(char* buf, int size);
HV_EXPORT char* get_executable_dir(char* buf, int size);
HV_EXPORT char* get_executable_file(char* buf, int size);
HV_EXPORT char* get_run_dir(char* buf, int size);
// random
HV_EXPORT int hv_rand(int min, int max);
HV_EXPORT char* hv_random_string(char *buf, int len);
// 1 y on yes true enable => true
HV_EXPORT bool hv_getboolean(const char* str);
// 1T2G3M4K5B => ?B
HV_EXPORT size_t hv_parse_size(const char* str);
// 1w2d3h4m5s => ?s
HV_EXPORT time_t hv_parse_time(const char* str);
// scheme:[//[user[:password]@]host[:port]][/path][?query][#fragment]
typedef enum {
HV_URL_SCHEME,
HV_URL_USERNAME,
HV_URL_PASSWORD,
HV_URL_HOST,
HV_URL_PORT,
HV_URL_PATH,
HV_URL_QUERY,
HV_URL_FRAGMENT,
HV_URL_FIELD_NUM,
} hurl_field_e;
typedef struct hurl_s {
struct {
unsigned short off;
unsigned short len;
} fields[HV_URL_FIELD_NUM];
unsigned short port;
} hurl_t;
HV_EXPORT int hv_parse_url(hurl_t* stURL, const char* strURL);
END_EXTERN_C
#endif // HV_BASE_H_
================================================
FILE: base/hbuf.h
================================================
#ifndef HV_BUF_H_
#define HV_BUF_H_
#include "hdef.h" // for MAX
#include "hbase.h" // for HV_ALLOC, HV_FREE
typedef struct hbuf_s {
char* base;
size_t len;
#ifdef __cplusplus
hbuf_s() {
base = NULL;
len = 0;
}
hbuf_s(void* data, size_t len) {
this->base = (char*)data;
this->len = len;
}
#endif
} hbuf_t;
typedef struct offset_buf_s {
char* base;
size_t len;
size_t offset;
#ifdef __cplusplus
offset_buf_s() {
base = NULL;
len = 0;
offset = 0;
}
offset_buf_s(void* data, size_t len) {
this->base = (char*)data;
this->len = len;
offset = 0;
}
#endif
} offset_buf_t;
typedef struct fifo_buf_s {
char* base;
size_t len;
size_t head;
size_t tail;
#ifdef __cplusplus
fifo_buf_s() {
base = NULL;
len = 0;
head = tail = 0;
}
fifo_buf_s(void* data, size_t len) {
this->base = (char*)data;
this->len = len;
head = tail = 0;
}
#endif
} fifo_buf_t;
#ifdef __cplusplus
class HBuf : public hbuf_t {
public:
HBuf() : hbuf_t() {
cleanup_ = false;
}
HBuf(void* data, size_t len) : hbuf_t(data, len) {
cleanup_ = false;
}
HBuf(size_t cap) { resize(cap); }
virtual ~HBuf() {
cleanup();
}
void* data() { return base; }
size_t size() { return len; }
bool isNull() { return base == NULL || len == 0; }
void cleanup() {
if (cleanup_) {
HV_FREE(base);
len = 0;
cleanup_ = false;
}
}
void resize(size_t cap) {
if (cap == len) return;
if (base == NULL) {
HV_ALLOC(base, cap);
}
else {
base = (char*)hv_realloc(base, cap, len);
}
len = cap;
cleanup_ = true;
}
void copy(void* data, size_t len) {
resize(len);
memcpy(base, data, len);
}
void copy(hbuf_t* buf) {
copy(buf->base, buf->len);
}
private:
bool cleanup_;
};
// VL: Variable-Length
class HVLBuf : public HBuf {
public:
HVLBuf() : HBuf() {_offset = _size = 0;}
HVLBuf(void* data, size_t len) : HBuf(data, len) {_offset = 0; _size = len;}
HVLBuf(size_t cap) : HBuf(cap) {_offset = _size = 0;}
virtual ~HVLBuf() {}
char* data() { return base + _offset; }
size_t size() { return _size; }
void push_front(void* ptr, size_t len) {
if (len > this->len - _size) {
size_t newsize = MAX(this->len, len)*2;
resize(newsize);
}
if (_offset < len) {
// move => end
memmove(base+this->len-_size, data(), _size);
_offset = this->len-_size;
}
memcpy(data()-len, ptr, len);
_offset -= len;
_size += len;
}
void push_back(void* ptr, size_t len) {
if (len > this->len - _size) {
size_t newsize = MAX(this->len, len)*2;
resize(newsize);
}
else if (len > this->len - _offset - _size) {
// move => start
memmove(base, data(), _size);
_offset = 0;
}
memcpy(data()+_size, ptr, len);
_size += len;
}
void pop_front(void* ptr, size_t len) {
if (len <= _size) {
if (ptr) {
memcpy(ptr, data(), len);
}
_offset += len;
if (_offset >= this->len) _offset = 0;
_size -= len;
}
}
void pop_back(void* ptr, size_t len) {
if (len <= _size) {
if (ptr) {
memcpy(ptr, data()+_size-len, len);
}
_size -= len;
}
}
void clear() {
_offset = _size = 0;
}
void prepend(void* ptr, size_t len) {
push_front(ptr, len);
}
void append(void* ptr, size_t len) {
push_back(ptr, len);
}
void insert(void* ptr, size_t len) {
push_back(ptr, len);
}
void remove(size_t len) {
pop_front(NULL, len);
}
private:
size_t _offset;
size_t _size;
};
class HRingBuf : public HBuf {
public:
HRingBuf() : HBuf() {_head = _tail = _size = 0;}
HRingBuf(size_t cap) : HBuf(cap) {_head = _tail = _size = 0;}
virtual ~HRingBuf() {}
char* alloc(size_t len) {
char* ret = NULL;
if (_head < _tail || _size == 0) {
// [_tail, this->len) && [0, _head)
if (this->len - _tail >= len) {
ret = base + _tail;
_tail += len;
if (_tail == this->len) _tail = 0;
}
else if (_head >= len) {
ret = base;
_tail = len;
}
}
else {
// [_tail, _head)
if (_head - _tail >= len) {
ret = base + _tail;
_tail += len;
}
}
_size += ret ? len : 0;
return ret;
}
void free(size_t len) {
_size -= len;
if (len <= this->len - _head) {
_head += len;
if (_head == this->len) _head = 0;
}
else {
_head = len;
}
}
void clear() {_head = _tail = _size = 0;}
size_t size() {return _size;}
private:
size_t _head;
size_t _tail;
size_t _size;
};
#endif
#endif // HV_BUF_H_
================================================
FILE: base/hdef.h
================================================
#ifndef HV_DEF_H_
#define HV_DEF_H_
#include "hplatform.h"
#ifndef ABS
#define ABS(n) ((n) > 0 ? (n) : -(n))
#endif
#ifndef NABS
#define NABS(n) ((n) < 0 ? (n) : -(n))
#endif
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
#endif
#ifndef BITSET
#define BITSET(p, n) (*(p) |= (1u << (n)))
#endif
#ifndef BITCLR
#define BITCLR(p, n) (*(p) &= ~(1u << (n)))
#endif
#ifndef BITGET
#define BITGET(i, n) ((i) & (1u << (n)))
#endif
/*
#ifndef CR
#define CR '\r'
#endif
#ifndef LF
#define LF '\n'
#endif
#ifndef CRLF
#define CRLF "\r\n"
#endif
*/
#define FLOAT_PRECISION 1e-6
#define FLOAT_EQUAL_ZERO(f) (ABS(f) < FLOAT_PRECISION)
#ifndef INFINITE
#define INFINITE (uint32_t)-1
#endif
/*
ASCII:
[0, 0x20) control-charaters
[0x20, 0x7F) printable-charaters
0x0A => LF
0x0D => CR
0x20 => SPACE
0x7F => DEL
[0x09, 0x0D] => \t\n\v\f\r
[0x30, 0x39] => 0~9
[0x41, 0x5A] => A~Z
[0x61, 0x7A] => a~z
*/
#ifndef IS_ALPHA
#define IS_ALPHA(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))
#endif
// NOTE: IS_NUM conflicts with mysql.h
#ifndef IS_DIGIT
#define IS_DIGIT(c) ((c) >= '0' && (c) <= '9')
#endif
#ifndef IS_ALPHANUM
#define IS_ALPHANUM(c) (IS_ALPHA(c) || IS_DIGIT(c))
#endif
#ifndef IS_CNTRL
#define IS_CNTRL(c) ((c) >= 0 && (c) < 0x20)
#endif
#ifndef IS_GRAPH
#define IS_GRAPH(c) ((c) >= 0x20 && (c) < 0x7F)
#endif
#ifndef IS_HEX
#define IS_HEX(c) (IS_DIGIT(c) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
#endif
#ifndef IS_LOWER
#define IS_LOWER(c) (((c) >= 'a' && (c) <= 'z'))
#endif
#ifndef IS_UPPER
#define IS_UPPER(c) (((c) >= 'A' && (c) <= 'Z'))
#endif
#ifndef LOWER
#define LOWER(c) ((c) | 0x20)
#endif
#ifndef UPPER
#define UPPER(c) ((c) & ~0x20)
#endif
// LD, LU, LLD, LLU for explicit conversion of integer
// #ifndef LD
// #define LD(v) ((long)(v))
// #endif
// #ifndef LU
// #define LU(v) ((unsigned long)(v))
// #endif
#ifndef LLD
#define LLD(v) ((long long)(v))
#endif
#ifndef LLU
#define LLU(v) ((unsigned long long)(v))
#endif
#ifndef _WIN32
// MAKEWORD, HIBYTE, LOBYTE
#ifndef MAKEWORD
#define MAKEWORD(h, l) ( (((WORD)h) << 8) | (l & 0xff) )
#endif
#ifndef HIBYTE
#define HIBYTE(w) ( (BYTE)(((WORD)w) >> 8) )
#endif
#ifndef LOBYTE
#define LOBYTE(w) ( (BYTE)(w & 0xff) )
#endif
// MAKELONG, HIWORD, LOWORD
#ifndef MAKELONG
#define MAKELONG(h, l) ( ((int32_t)h) << 16 | (l & 0xffff) )
#endif
#ifndef HIWORD
#define HIWORD(n) ( (WORD)(((int32_t)n) >> 16) )
#endif
#ifndef LOWORD
#define LOWORD(n) ( (WORD)(n & 0xffff) )
#endif
#endif // _WIN32
// MAKEINT64, HIINT, LOINT
#ifndef MAKEINT64
#define MAKEINT64(h, l) ( ((int64_t)h) << 32 | (l & 0xffffffff) )
#endif
#ifndef HIINT
#define HIINT(n) ( (int32_t)(((int64_t)n) >> 32) )
#endif
#ifndef LOINT
#define LOINT(n) ( (int32_t)(n & 0xffffffff) )
#endif
#ifndef MAKE_FOURCC
#define MAKE_FOURCC(a, b, c, d) \
( ((uint32)d) | ( ((uint32)c) << 8 ) | ( ((uint32)b) << 16 ) | ( ((uint32)a) << 24 ) )
#endif
#ifndef MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
#ifndef LIMIT
#define LIMIT(lower, v, upper) ((v) < (lower) ? (lower) : (v) > (upper) ? (upper) : (v))
#endif
#ifndef MAX_PATH
#define MAX_PATH 260
#endif
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void*)0)
#endif
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef SAFE_ALLOC
#define SAFE_ALLOC(p, size)\
do {\
void* ptr = malloc(size);\
if (!ptr) {\
fprintf(stderr, "malloc failed!\n");\
exit(-1);\
}\
memset(ptr, 0, size);\
*(void**)&(p) = ptr;\
} while(0)
#endif
#ifndef SAFE_FREE
#define SAFE_FREE(p) do {if (p) {free(p); (p) = NULL;}} while(0)
#endif
#ifndef SAFE_DELETE
#define SAFE_DELETE(p) do {if (p) {delete (p); (p) = NULL;}} while(0)
#endif
#ifndef SAFE_DELETE_ARRAY
#define SAFE_DELETE_ARRAY(p) do {if (p) {delete[] (p); (p) = NULL;}} while(0)
#endif
#ifndef SAFE_RELEASE
#define SAFE_RELEASE(p) do {if (p) {(p)->release(); (p) = NULL;}} while(0)
#endif
#ifndef SAFE_CLOSE
#define SAFE_CLOSE(fd) do {if ((fd) >= 0) {close(fd); (fd) = -1;}} while(0)
#endif
#define STRINGIFY(x) STRINGIFY_HELPER(x)
#define STRINGIFY_HELPER(x) #x
#define STRINGCAT(x, y) STRINGCAT_HELPER(x, y)
#define STRINGCAT_HELPER(x, y) x##y
#ifndef offsetof
#define offsetof(type, member) \
((size_t)(&((type*)0)->member))
#endif
#ifndef offsetofend
#define offsetofend(type, member) \
(offsetof(type, member) + sizeof(((type*)0)->member))
#endif
#ifndef container_of
#define container_of(ptr, type, member) \
((type*)((char*)(ptr) - offsetof(type, member)))
#endif
#ifdef PRINT_DEBUG
#define printd(...) printf(__VA_ARGS__)
#else
#define printd(...)
#endif
#ifdef PRINT_ERROR
#define printe(...) fprintf(stderr, __VA_ARGS__)
#else
#define printe(...)
#endif
#endif // HV_DEF_H_
================================================
FILE: base/heap.h
================================================
#ifndef HV_HEAP_H_
#define HV_HEAP_H_
#include <assert.h> // for assert
#include <stddef.h> // for NULL
struct heap_node {
struct heap_node* parent;
struct heap_node* left;
struct heap_node* right;
};
typedef int (*heap_compare_fn)(const struct heap_node* lhs, const struct heap_node* rhs);
struct heap {
struct heap_node* root;
int nelts;
// if compare is less_than, root is min of heap
// if compare is larger_than, root is max of heap
heap_compare_fn compare;
};
static inline void heap_init(struct heap* heap, heap_compare_fn fn) {
heap->root = NULL;
heap->nelts = 0;
heap->compare = fn;
}
// replace s with r
static inline void heap_replace(struct heap* heap, struct heap_node* s, struct heap_node* r) {
// s->parent->child, s->left->parent, s->right->parent
if (s->parent == NULL) heap->root = r;
else if (s->parent->left == s) s->parent->left = r;
else if (s->parent->right == s) s->parent->right = r;
if (s->left) s->left->parent = r;
if (s->right) s->right->parent = r;
if (r) {
//*r = *s;
r->parent = s->parent;
r->left = s->left;
r->right = s->right;
}
}
static inline void heap_swap(struct heap* heap, struct heap_node* parent, struct heap_node* child) {
assert(child->parent == parent && (parent->left == child || parent->right == child));
struct heap_node* pparent = parent->parent;
struct heap_node* lchild = child->left;
struct heap_node* rchild = child->right;
struct heap_node* sibling = NULL;
if (pparent == NULL) heap->root = child;
else if (pparent->left == parent) pparent->left = child;
else if (pparent->right == parent) pparent->right = child;
if (lchild) lchild->parent = parent;
if (rchild) rchild->parent = parent;
child->parent = pparent;
if (parent->left == child) {
sibling = parent->right;
child->left = parent;
child->right = sibling;
} else {
sibling = parent->left;
child->left = sibling;
child->right = parent;
}
if (sibling) sibling->parent = child;
parent->parent = child;
parent->left = lchild;
parent->right = rchild;
}
static inline void heap_insert(struct heap* heap, struct heap_node* node) {
// get last => insert node => sift up
// 0: left, 1: right
int path = 0;
int n,d;
++heap->nelts;
// traverse from bottom to up, get path of last node
for (d = 0, n = heap->nelts; n >= 2; ++d, n>>=1) {
path = (path << 1) | (n & 1);
}
// get last->parent by path
struct heap_node* parent = heap->root;
while(d > 1) {
parent = (path & 1) ? parent->right : parent->left;
--d;
path >>= 1;
}
// insert node
node->parent = parent;
if (parent == NULL) heap->root = node;
else if (path & 1) parent->right = node;
else parent->left = node;
// sift up
if (heap->compare) {
while (node->parent && heap->compare(node, node->parent)) {
heap_swap(heap, node->parent, node);
}
}
}
static inline void heap_remove(struct heap* heap, struct heap_node* node) {
if (heap->nelts == 0) return;
// get last => replace node with last => sift down and sift up
// 0: left, 1: right
int path = 0;
int n,d;
// traverse from bottom to up, get path of last node
for (d = 0, n = heap->nelts; n >= 2; ++d, n>>=1) {
path = (path << 1) | (n & 1);
}
--heap->nelts;
// get last->parent by path
struct heap_node* parent = heap->root;
while(d > 1) {
parent = (path & 1) ? parent->right : parent->left;
--d;
path >>= 1;
}
// replace node with last
struct heap_node* last = NULL;
if (parent == NULL) {
return;
}
else if (path & 1) {
last = parent->right;
parent->right = NULL;
}
else {
last = parent->left;
parent->left = NULL;
}
if (last == NULL) {
if (heap->root == node) {
heap->root = NULL;
}
return;
}
heap_replace(heap, node, last);
node->parent = node->left = node->right = NULL;
if (!heap->compare) return;
struct heap_node* v = last;
struct heap_node* est = NULL;
// sift down
while (1) {
est = v;
if (v->left) est = heap->compare(est, v->left) ? est : v->left;
if (v->right) est = heap->compare(est, v->right) ? est : v->right;
if (est == v) break;
heap_swap(heap, v, est);
}
// sift up
while (v->parent && heap->compare(v, v->parent)) {
heap_swap(heap, v->parent, v);
}
}
static inline void heap_dequeue(struct heap* heap) {
heap_remove(heap, heap->root);
}
#endif // HV_HEAP_H_
================================================
FILE: base/hendian.h
================================================
#ifndef HV_ENDIAN_H_
#define HV_ENDIAN_H_
#include "hplatform.h"
#if defined(OS_MAC)
#include <libkern/OSByteOrder.h>
#define htobe16(v) OSSwapHostToBigInt16(v)
#define htobe32(v) OSSwapHostToBigInt32(v)
#define htobe64(v) OSSwapHostToBigInt64(v)
#define be16toh(v) OSSwapBigToHostInt16(v)
#define be32toh(v) OSSwapBigToHostInt32(v)
#define be64toh(v) OSSwapBigToHostInt64(v)
#define htole16(v) OSSwapHostToLittleInt16(v)
#define htole32(v) OSSwapHostToLittleInt32(v)
#define htole64(v) OSSwapHostToLittleInt64(v)
#define le16toh(v) OSSwapLittleToHostInt16(v)
#define le32toh(v) OSSwapLittleToHostInt32(v)
#define le64toh(v) OSSwapLittleToHostInt64(v)
#elif defined(OS_WIN)
#if _WIN32_WINNT < _WIN32_WINNT_WIN8
/*
* Byte order conversion functions for 64-bit integers and 32 + 64 bit
* floating-point numbers. IEEE big-endian format is used for the
* network floating point format.
*/
#define _WS2_32_WINSOCK_SWAP_LONG(l) \
( ( ((l) >> 24) & 0x000000FFL ) | \
( ((l) >> 8) & 0x0000FF00L ) | \
( ((l) << 8) & 0x00FF0000L ) | \
( ((l) << 24) & 0xFF000000L ) )
#define _WS2_32_WINSOCK_SWAP_LONGLONG(l) \
( ( ((l) >> 56) & 0x00000000000000FFLL ) | \
( ((l) >> 40) & 0x000000000000FF00LL ) | \
( ((l) >> 24) & 0x0000000000FF0000LL ) | \
( ((l) >> 8) & 0x00000000FF000000LL ) | \
( ((l) << 8) & 0x000000FF00000000LL ) | \
( ((l) << 24) & 0x0000FF0000000000LL ) | \
( ((l) << 40) & 0x00FF000000000000LL ) | \
( ((l) << 56) & 0xFF00000000000000LL ) )
#ifndef htonll
__inline unsigned __int64 htonll ( unsigned __int64 Value )
{
const unsigned __int64 Retval = _WS2_32_WINSOCK_SWAP_LONGLONG (Value);
return Retval;
}
#endif /* htonll */
#ifndef ntohll
__inline unsigned __int64 ntohll ( unsigned __int64 Value )
{
const unsigned __int64 Retval = _WS2_32_WINSOCK_SWAP_LONGLONG (Value);
return Retval;
}
#endif /* ntohll */
#ifndef htonf
__inline unsigned __int32 htonf ( float Value )
{
unsigned __int32 Tempval;
unsigned __int32 Retval;
Tempval = *(unsigned __int32*)(&Value);
Retval = _WS2_32_WINSOCK_SWAP_LONG (Tempval);
return Retval;
}
#endif /* htonf */
#ifndef ntohf
__inline float ntohf ( unsigned __int32 Value )
{
const unsigned __int32 Tempval = _WS2_32_WINSOCK_SWAP_LONG (Value);
float Retval;
*((unsigned __int32*)&Retval) = Tempval;
return Retval;
}
#endif /* ntohf */
#ifndef htond
__inline unsigned __int64 htond ( double Value )
{
unsigned __int64 Tempval;
unsigned __int64 Retval;
Tempval = *(unsigned __int64*)(&Value);
Retval = _WS2_32_WINSOCK_SWAP_LONGLONG (Tempval);
return Retval;
}
#endif /* htond */
#ifndef ntohd
__inline double ntohd ( unsigned __int64 Value )
{
const unsigned __int64 Tempval = _WS2_32_WINSOCK_SWAP_LONGLONG (Value);
double Retval;
*((unsigned __int64*)&Retval) = Tempval;
return Retval;
}
#endif /* ntohd */
#endif
#define htobe16(v) htons(v)
#define htobe32(v) htonl(v)
#define htobe64(v) htonll(v)
#define be16toh(v) ntohs(v)
#define be32toh(v) ntohl(v)
#define be64toh(v) ntohll(v)
#if (BYTE_ORDER == LITTLE_ENDIAN)
#define htole16(v) (v)
#define htole32(v) (v)
#define htole64(v) (v)
#define le16toh(v) (v)
#define le32toh(v) (v)
#define le64toh(v) (v)
#elif (BYTE_ORDER == BIG_ENDIAN)
#define htole16(v) __builtin_bswap16(v)
#define htole32(v) __builtin_bswap32(v)
#define htole64(v) __builtin_bswap64(v)
#define le16toh(v) __builtin_bswap16(v)
#define le32toh(v) __builtin_bswap32(v)
#define le64toh(v) __builtin_bswap64(v)
#endif
#elif HAVE_ENDIAN_H
#include <endian.h>
#elif HAVE_SYS_ENDIAN_H
#include <sys/endian.h>
#else
#warning "Not found endian.h!"
#endif
#define PI8(p) *(int8_t*)(p)
#define PI16(p) *(int16_t*)(p)
#define PI32(p) *(int32_t*)(p)
#define PI64(p) *(int64_t*)(p)
#define PU8(p) *(uint8_t*)(p)
#define PU16(p) *(uint16_t*)(p)
#define PU32(p) *(uint32_t*)(p)
#define PU64(p) *(uint64_t*)(p)
#define PF32(p) *(float*)(p)
#define PF64(p) *(double*)(p)
#define GET_BE16(p) be16toh(PU16(p))
#define GET_BE32(p) be32toh(PU32(p))
#define GET_BE64(p) be64toh(PU64(p))
#define GET_LE16(p) le16toh(PU16(p))
#define GET_LE32(p) le32toh(PU32(p))
#define GET_LE64(p) le64toh(PU64(p))
#define PUT_BE16(p, v) PU16(p) = htobe16(v)
#define PUT_BE32(p, v) PU32(p) = htobe32(v)
#define PUT_BE64(p, v) PU64(p) = htobe64(v)
#define PUT_LE16(p, v) PU16(p) = htole16(v)
#define PUT_LE32(p, v) PU32(p) = htole32(v)
#define PUT_LE64(p, v) PU64(p) = htole64(v)
// NOTE: uint8_t* p = (uint8_t*)buf;
#define POP_BE8(p, v) v = *p; ++p
#define POP_BE16(p, v) v = be16toh(PU16(p)); p += 2
#define POP_BE32(p, v) v = be32toh(PU32(p)); p += 4
#define POP_BE64(p, v) v = be64toh(PU64(p)); p += 8
#define POP_LE8(p, v) v= *p; ++p
#define POP_LE16(p, v) v = le16toh(PU16(p)); p += 2
#define POP_LE32(p, v) v = le32toh(PU32(p)); p += 4
#define POP_LE64(p, v) v = le64toh(PU64(p)); p += 8
#define PUSH_BE8(p, v) *p = v; ++p
#define PUSH_BE16(p, v) PU16(p) = htobe16(v); p += 2
#define PUSH_BE32(p, v) PU32(p) = htobe32(v); p += 4
#define PUSH_BE64(p, v) PU64(p) = htobe64(v); p += 8
#define PUSH_LE8(p, v) *p = v; ++p
#define PUSH_LE16(p, v) PU16(p) = htole16(v); p += 2
#define PUSH_LE32(p, v) PU32(p) = htole32(v); p += 4
#define PUSH_LE64(p, v) PU64(p) = htole64(v); p += 8
// NOTE: NET_ENDIAN = BIG_ENDIAN
#define POP8(p, v) POP_BE8(p, v)
#define POP16(p, v) POP_BE16(p, v)
#define POP32(p, v) POP_BE32(p, v)
#define POP64(p, v) POP_BE64(p, v)
#define POP_N(p, v, n) memcpy(v, p, n); p += n
#define PUSH8(p, v) PUSH_BE8(p, v)
#define PUSH16(p, v) PUSH_BE16(p, v)
#define PUSH32(p, v) PUSH_BE32(p, v)
#define PUSH64(p, v) PUSH_BE64(p, v)
#define PUSH_N(p, v, n) memcpy(p, v, n); p += n
static inline int detect_endian() {
union {
char c;
short s;
} u;
u.s = 0x1122;
return u.c ==0x11 ? BIG_ENDIAN : LITTLE_ENDIAN;
}
#ifdef __cplusplus
template <typename T>
uint8_t* serialize(uint8_t* buf, T value, int host_endian = LITTLE_ENDIAN, int buf_endian = BIG_ENDIAN) {
size_t size = sizeof(T);
uint8_t* pDst = buf;
uint8_t* pSrc = (uint8_t*)&value;
if (host_endian == buf_endian) {
memcpy(pDst, pSrc, size);
}
else {
for (int i = 0; i < size; ++i) {
pDst[i] = pSrc[size-i-1];
}
}
return buf+size;
}
template <typename T>
uint8_t* deserialize(uint8_t* buf, T* value, int host_endian = LITTLE_ENDIAN, int buf_endian = BIG_ENDIAN) {
size_t size = sizeof(T);
uint8_t* pSrc = buf;
uint8_t* pDst = (uint8_t*)value;
if (host_endian == buf_endian) {
memcpy(pDst, pSrc, size);
}
else {
for (int i = 0; i < size; ++i) {
pDst[i] = pSrc[size-i-1];
}
}
return buf+size;
}
#endif // __cplusplus
#endif // HV_ENDIAN_H_
================================================
FILE: base/herr.c
================================================
#include "herr.h"
#include <string.h> // for strerror
// errcode => errmsg
const char* hv_strerror(int err) {
if (err > 0 && err <= SYS_NERR) {
return strerror(err);
}
switch (err) {
#define F(errcode, name, errmsg) \
case errcode: return errmsg;
FOREACH_ERR(F)
#undef F
default:
return "Undefined error";
}
}
================================================
FILE: base/herr.h
================================================
#ifndef HV_ERR_H_
#define HV_ERR_H_
#include <errno.h>
#include "hexport.h"
#ifndef SYS_NERR
#define SYS_NERR 133
#endif
// F(errcode, name, errmsg)
// [1, 133]
#define FOREACH_ERR_SYS(F)
// [1xx~5xx]
#define FOREACH_ERR_STATUS(F)
// [1xxx]
#define FOREACH_ERR_COMMON(F) \
F(0, OK, "OK") \
F(1000, UNKNOWN, "Unknown error") \
\
F(1001, NULL_PARAM, "Null parameter") \
F(1002, NULL_POINTER, "Null pointer") \
F(1003, NULL_DATA, "Null data") \
F(1004, NULL_HANDLE, "Null handle") \
\
F(1011, INVALID_PARAM, "Invalid parameter")\
F(1012, INVALID_POINTER, "Invalid pointer") \
F(1013, INVALID_DATA, "Invalid data") \
F(1014, INVALID_HANDLE, "Invalid handle") \
F(1015, INVALID_JSON, "Invalid json") \
F(1016, INVALID_XML, "Invalid xml") \
F(1017, INVALID_FMT, "Invalid format") \
F(1018, INVALID_PROTOCOL, "Invalid protocol") \
F(1019, INVALID_PACKAGE, "Invalid package") \
\
F(1021, OUT_OF_RANGE, "Out of range") \
F(1022, OVER_LIMIT, "Over the limit") \
F(1023, MISMATCH, "Mismatch") \
F(1024, PARSE, "Parse failed") \
\
F(1030, OPEN_FILE, "Open file failed") \
F(1031, SAVE_FILE, "Save file failed") \
F(1032, READ_FILE, "Read file failed") \
F(1033, WRITE_FILE, "Write file failed")\
\
F(1040, SSL, "SSL/TLS error") \
F(1041, NEW_SSL_CTX, "New SSL_CTX failed") \
F(1042, NEW_SSL, "New SSL failed") \
F(1043, SSL_HANDSHAKE, "SSL handshake failed") \
\
F(1100, TASK_TIMEOUT, "Task timeout") \
F(1101, TASK_QUEUE_FULL, "Task queue full") \
F(1102, TASK_QUEUE_EMPTY, "Task queue empty") \
\
F(1400, REQUEST, "Bad request") \
F(1401, RESPONSE, "Bad response") \
// [-1xxx]
#define FOREACH_ERR_FUNC(F) \
F(-1001, MALLOC, "malloc() error") \
F(-1002, REALLOC, "realloc() error") \
F(-1003, CALLOC, "calloc() error") \
F(-1004, FREE, "free() error") \
\
F(-1011, SOCKET, "socket() error") \
F(-1012, BIND, "bind() error") \
F(-1013, LISTEN, "listen() error") \
F(-1014, ACCEPT, "accept() error") \
F(-1015, CONNECT, "connect() error") \
F(-1016, RECV, "recv() error") \
F(-1017, SEND, "send() error") \
F(-1018, RECVFROM, "recvfrom() error") \
F(-1019, SENDTO, "sendto() error") \
F(-1020, SETSOCKOPT, "setsockopt() error") \
F(-1021, GETSOCKOPT, "getsockopt() error") \
// grpc [4xxx]
#define FOREACH_ERR_GRPC(F) \
F(4000, GRPC_FIRST, "grpc no error") \
F(4001, GRPC_STATUS_CANCELLED, "grpc status: cancelled") \
F(4002, GRPC_STATUS_UNKNOWN, "grpc unknown error") \
F(4003, GRPC_STATUS_INVALID_ARGUMENT, "grpc status: invalid argument")\
F(4004, GRPC_STATUS_DEADLINE, "grpc status: deadline") \
F(4005, GRPC_STATUS_NOT_FOUND, "grpc status: not found") \
F(4006, GRPC_STATUS_ALREADY_EXISTS, "grpc status: already exists") \
F(4007, GRPC_STATUS_PERMISSION_DENIED, "grpc status: permission denied") \
F(4008, GRPC_STATUS_RESOURCE_EXHAUSTED, "grpc status: resource exhausted") \
F(4009, GRPC_STATUS_FAILED_PRECONDITION,"grpc status: failed precondition") \
F(4010, GRPC_STATUS_ABORTED, "grpc status: aborted") \
F(4011, GRPC_STATUS_OUT_OF_RANGE, "grpc status: out of range") \
F(4012, GRPC_STATUS_UNIMPLEMENTED, "grpc status: unimplemented") \
F(4013, GRPC_STATUS_INTERNAL, "grpc internal error") \
F(4014, GRPC_STATUS_UNAVAILABLE, "grpc service unavailable") \
F(4015, GRPC_STATUS_DATA_LOSS, "grpc status: data loss") \
#define FOREACH_ERR(F) \
FOREACH_ERR_COMMON(F) \
FOREACH_ERR_FUNC(F) \
FOREACH_ERR_GRPC(F) \
#undef ERR_OK // prevent conflict
enum {
#define F(errcode, name, errmsg) ERR_##name = errcode,
FOREACH_ERR(F)
#undef F
};
#ifdef __cplusplus
extern "C" {
#endif
// errcode => errmsg
HV_EXPORT const char* hv_strerror(int err);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // HV_ERR_H_
================================================
FILE: base/hlog.c
================================================
#include "hlog.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
//#include "hmutex.h"
#ifdef _WIN32
#pragma warning (disable: 4244) // conversion loss of data
#include <windows.h>
#define hmutex_t CRITICAL_SECTION
#define hmutex_init InitializeCriticalSection
#define hmutex_destroy DeleteCriticalSection
#define hmutex_lock EnterCriticalSection
#define hmutex_unlock LeaveCriticalSection
#else
#include <sys/time.h> // for gettimeofday
#include <pthread.h>
#define hmutex_t pthread_mutex_t
#define hmutex_init(mutex) pthread_mutex_init(mutex, NULL)
#define hmutex_destroy pthread_mutex_destroy
#define hmutex_lock pthread_mutex_lock
#define hmutex_unlock pthread_mutex_unlock
#endif
//#include "htime.h"
#define SECONDS_PER_HOUR 3600
#define SECONDS_PER_DAY 86400 // 24*3600
#define SECONDS_PER_WEEK 604800 // 7*24*3600;
static int s_gmtoff = 28800; // 8*3600
struct logger_s {
logger_handler handler;
unsigned int bufsize;
char* buf;
int level;
int enable_color;
char format[64];
// for file logger
char filepath[256];
unsigned long long max_filesize;
float truncate_percent;
int remain_days;
int enable_fsync;
FILE* fp_;
char cur_logfile[256];
time_t last_logfile_ts;
int can_write_cnt;
hmutex_t mutex_; // thread-safe
};
static void logger_init(logger_t* logger) {
logger->handler = NULL;
logger->bufsize = DEFAULT_LOG_MAX_BUFSIZE;
logger->buf = (char*)malloc(logger->bufsize);
logger->level = DEFAULT_LOG_LEVEL;
logger->enable_color = 0;
// NOTE: format is faster 6% than snprintf
// logger->format[0] = '\0';
strncpy(logger->format, DEFAULT_LOG_FORMAT, sizeof(logger->format) - 1);
logger->fp_ = NULL;
logger->max_filesize = DEFAULT_LOG_MAX_FILESIZE;
logger->truncate_percent = DEFAULT_LOG_TRUNCATE_PERCENT;
logger->remain_days = DEFAULT_LOG_REMAIN_DAYS;
logger->enable_fsync = 1;
logger_set_file(logger, DEFAULT_LOG_FILE);
logger->last_logfile_ts = 0;
logger->can_write_cnt = -1;
hmutex_init(&logger->mutex_);
}
logger_t* logger_create() {
// init gmtoff here
time_t ts = time(NULL);
struct tm* local_tm = localtime(&ts);
int local_hour = local_tm->tm_hour;
struct tm* gmt_tm = gmtime(&ts);
int gmt_hour = gmt_tm->tm_hour;
s_gmtoff = (local_hour - gmt_hour) * SECONDS_PER_HOUR;
logger_t* logger = (logger_t*)malloc(sizeof(logger_t));
logger_init(logger);
return logger;
}
void logger_destroy(logger_t* logger) {
if (logger) {
if (logger->buf) {
free(logger->buf);
logger->buf = NULL;
}
if (logger->fp_) {
fclose(logger->fp_);
logger->fp_ = NULL;
}
hmutex_destroy(&logger->mutex_);
free(logger);
}
}
void logger_set_handler(logger_t* logger, logger_handler fn) {
logger->handler = fn;
}
void logger_set_level(logger_t* logger, int level) {
logger->level = level;
}
void logger_set_level_by_str(logger_t* logger, const char* szLoglevel) {
int loglevel = DEFAULT_LOG_LEVEL;
if (strcmp(szLoglevel, "VERBOSE") == 0) {
loglevel = LOG_LEVEL_VERBOSE;
} else if (strcmp(szLoglevel, "DEBUG") == 0) {
loglevel = LOG_LEVEL_DEBUG;
} else if (strcmp(szLoglevel, "INFO") == 0) {
loglevel = LOG_LEVEL_INFO;
} else if (strcmp(szLoglevel, "WARN") == 0) {
loglevel = LOG_LEVEL_WARN;
} else if (strcmp(szLoglevel, "ERROR") == 0) {
loglevel = LOG_LEVEL_ERROR;
} else if (strcmp(szLoglevel, "FATAL") == 0) {
loglevel = LOG_LEVEL_FATAL;
} else if (strcmp(szLoglevel, "SILENT") == 0) {
loglevel = LOG_LEVEL_SILENT;
} else {
loglevel = DEFAULT_LOG_LEVEL;
}
logger->level = loglevel;
}
void logger_set_format(logger_t* logger, const char* format) {
if (format) {
strncpy(logger->format, format, sizeof(logger->format) - 1);
} else {
logger->format[0] = '\0';
}
}
void logger_set_remain_days(logger_t* logger, int days) {
logger->remain_days = days;
}
void logger_set_truncate_percent(logger_t* logger, float percent) {
assert(percent <= 1.0f);
logger->truncate_percent = percent;
}
void logger_set_max_bufsize(logger_t* logger, unsigned int bufsize) {
logger->bufsize = bufsize;
logger->buf = (char*)realloc(logger->buf, bufsize);
}
void logger_enable_color(logger_t* logger, int on) {
logger->enable_color = on;
}
void logger_set_file(logger_t* logger, const char* filepath) {
strncpy(logger->filepath, filepath, sizeof(logger->filepath) - 1);
// remove suffix .log
char* suffix = strrchr(logger->filepath, '.');
if (suffix && strcmp(suffix, ".log") == 0) {
*suffix = '\0';
}
}
void logger_set_max_filesize(logger_t* logger, unsigned long long filesize) {
logger->max_filesize = filesize;
}
void logger_set_max_filesize_by_str(logger_t* logger, const char* str) {
int num = atoi(str);
if (num <= 0) return;
// 16 16M 16MB
const char* e = str;
while (*e != '\0') ++e;
--e;
char unit;
if (*e >= '0' && *e <= '9') unit = 'M';
else if (*e == 'B') unit = *(e-1);
else unit = *e;
unsigned long long filesize = num;
switch (unit) {
case 'K': filesize <<= 10; break;
case 'M': filesize <<= 20; break;
case 'G': filesize <<= 30; break;
default: filesize <<= 20; break;
}
logger->max_filesize = filesize;
}
void logger_enable_fsync(logger_t* logger, int on) {
logger->enable_fsync = on;
}
void logger_fsync(logger_t* logger) {
hmutex_lock(&logger->mutex_);
if (logger->fp_) {
fflush(logger->fp_);
}
hmutex_unlock(&logger->mutex_);
}
const char* logger_get_cur_file(logger_t* logger) {
return logger->cur_logfile;
}
static void logfile_name(const char* filepath, time_t ts, char* buf, int len) {
struct tm* tm = localtime(&ts);
snprintf(buf, len, "%s.%04d%02d%02d.log",
filepath,
tm->tm_year+1900,
tm->tm_mon+1,
tm->tm_mday);
}
static void logfile_truncate(logger_t* logger) {
// close
if (logger->fp_) {
fclose(logger->fp_);
logger->fp_ = NULL;
}
char tmp_logfile[sizeof(logger->cur_logfile) + 4] = {0};
FILE* tmpfile = NULL;
if (logger->truncate_percent < 1.0f) {
snprintf(tmp_logfile, sizeof(tmp_logfile), "%s.tmp", logger->cur_logfile);
tmpfile = fopen(tmp_logfile, "w");
}
if (tmpfile) {
// truncate percent
logger->fp_ = fopen(logger->cur_logfile, "r");
if (logger->fp_) {
fseek(logger->fp_, 0, SEEK_END);
long filesize = ftell(logger->fp_);
long truncate_size = (long)((double)filesize * logger->truncate_percent);
fseek(logger->fp_, -(filesize - truncate_size), SEEK_CUR);
char buf[4096] = {0};
const char* pbuf = buf;
size_t nread = 0;
char find_newline = 0;
while ((nread = fread(buf, 1, sizeof(buf), logger->fp_)) > 0) {
pbuf = buf;
if (find_newline == 0) {
while (nread > 0) {
if (*pbuf == '\n') {
find_newline = 1;
++pbuf;
--nread;
break;
}
++pbuf;
--nread;
}
}
if (nread > 0) {
fwrite(pbuf, 1, nread, tmpfile);
}
}
fclose(tmpfile);
fclose(logger->fp_);
logger->fp_ = NULL;
remove(logger->cur_logfile);
rename(tmp_logfile, logger->cur_logfile);
}
} else {
// truncate all
// remove(logger->cur_logfile);
logger->fp_ = fopen(logger->cur_logfile, "w");
if (logger->fp_) {
fclose(logger->fp_);
logger->fp_ = NULL;
}
}
// reopen
logger->fp_ = fopen(logger->cur_logfile, "a");
}
static FILE* logfile_shift(logger_t* logger) {
time_t ts_now = time(NULL);
int interval_days = logger->last_logfile_ts == 0 ? 0 : (ts_now+s_gmtoff) / SECONDS_PER_DAY - (logger->last_logfile_ts+s_gmtoff) / SECONDS_PER_DAY;
if (logger->fp_ == NULL || interval_days > 0) {
// close old logfile
if (logger->fp_) {
fclose(logger->fp_);
logger->fp_ = NULL;
}
else {
interval_days = 30;
}
if (logger->remain_days >= 0) {
char rm_logfile[256] = {0};
if (interval_days >= logger->remain_days) {
// remove [today-interval_days, today-remain_days] logfile
for (int i = interval_days; i >= logger->remain_days; --i) {
time_t ts_rm = ts_now - i * SECONDS_PER_DAY;
logfile_name(logger->filepath, ts_rm, rm_logfile, sizeof(rm_logfile));
remove(rm_logfile);
}
}
else {
// remove today-remain_days logfile
time_t ts_rm = ts_now - logger->remain_days * SECONDS_PER_DAY;
logfile_name(logger->filepath, ts_rm, rm_logfile, sizeof(rm_logfile));
remove(rm_logfile);
}
}
}
// open today logfile
if (logger->fp_ == NULL) {
logfile_name(logger->filepath, ts_now, logger->cur_logfile, sizeof(logger->cur_logfile));
logger->fp_ = fopen(logger->cur_logfile, "a");
logger->last_logfile_ts = ts_now;
}
// NOTE: estimate can_write_cnt to avoid frequent fseek/ftell
if (logger->fp_ && --logger->can_write_cnt < 0) {
fseek(logger->fp_, 0, SEEK_END);
long filesize = ftell(logger->fp_);
if (filesize > logger->max_filesize) {
logfile_truncate(logger);
} else {
logger->can_write_cnt = (logger->max_filesize - filesize) / logger->bufsize;
}
}
return logger->fp_;
}
static void logfile_write(logger_t* logger, const char* buf, int len) {
FILE* fp = logfile_shift(logger);
if (fp) {
fwrite(buf, 1, len, fp);
if (logger->enable_fsync) {
fflush(fp);
}
}
}
static int i2a(int i, char* buf, int len) {
for (int l = len - 1; l >= 0; --l) {
if (i == 0) {
buf[l] = '0';
} else {
buf[l] = i % 10 + '0';
i /= 10;
}
}
return len;
}
int logger_print(logger_t* logger, int level, const char* fmt, ...) {
if (level < logger->level)
return -10;
int year,month,day,hour,min,sec,us;
#ifdef _WIN32
SYSTEMTIME tm;
GetLocalTime(&tm);
year = tm.wYear;
month = tm.wMonth;
day = tm.wDay;
hour = tm.wHour;
min = tm.wMinute;
sec = tm.wSecond;
us = tm.wMilliseconds * 1000;
#else
struct timeval tv;
struct tm* tm = NULL;
gettimeofday(&tv, NULL);
time_t tt = tv.tv_sec;
tm = localtime(&tt);
year = tm->tm_year + 1900;
month = tm->tm_mon + 1;
day = tm->tm_mday;
hour = tm->tm_hour;
min = tm->tm_min;
sec = tm->tm_sec;
us = tv.tv_usec;
#endif
const char* pcolor = "";
const char* plevel = "";
#define XXX(id, str, clr) \
case id: plevel = str; pcolor = clr; break;
switch (level) {
LOG_LEVEL_MAP(XXX)
}
#undef XXX
// lock logger->buf
hmutex_lock(&logger->mutex_);
char* buf = logger->buf;
int bufsize = logger->bufsize;
int len = 0;
if (logger->enable_color) {
len = snprintf(buf, bufsize, "%s", pcolor);
}
const char* p = logger->format;
if (*p) {
while (*p) {
if (*p == '%') {
switch(*++p) {
case 'y':
len += i2a(year, buf + len, 4);
break;
case 'm':
len += i2a(month, buf + len, 2);
break;
case 'd':
len += i2a(day, buf + len, 2);
break;
case 'H':
len += i2a(hour, buf + len, 2);
break;
case 'M':
len += i2a(min, buf + len, 2);
break;
case 'S':
len += i2a(sec, buf + len, 2);
break;
case 'z':
len += i2a(us/1000, buf + len, 3);
break;
case 'Z':
len += i2a(us, buf + len, 6);
break;
case 'l':
buf[len++] = *plevel;
break;
case 'L':
for (int i = 0; i < 5; ++i) {
buf[len++] = plevel[i];
}
break;
case 's':
{
va_list ap;
va_start(ap, fmt);
len += vsnprintf(buf + len, bufsize - len, fmt, ap);
va_end(ap);
}
break;
case '%':
buf[len++] = '%';
break;
default: break;
}
} else {
buf[len++] = *p;
}
++p;
if (len >= bufsize) break;
}
} else {
len += snprintf(buf + len, bufsize - len, "%04d-%02d-%02d %02d:%02d:%02d.%03d %s ",
year, month, day, hour, min, sec, us/1000,
plevel);
va_list ap;
va_start(ap, fmt);
len += vsnprintf(buf + len, bufsize - len, fmt, ap);
va_end(ap);
}
if (logger->enable_color && len < bufsize) {
len += snprintf(buf + len, bufsize - len, "%s", CLR_CLR);
}
if (len < bufsize) {
buf[len++] = '\n';
} else {
buf[bufsize - 1] = '\n';
len = bufsize;
}
if (logger->handler) {
logger->handler(level, buf, len);
}
else {
logfile_write(logger, buf, len);
}
hmutex_unlock(&logger->mutex_);
return len;
}
static logger_t* s_logger = NULL;
logger_t* hv_default_logger() {
if (s_logger == NULL) {
s_logger = logger_create();
atexit(hv_destroy_default_logger);
}
return s_logger;
}
void hv_destroy_default_logger(void) {
if (s_logger) {
logger_fsync(s_logger);
logger_destroy(s_logger);
s_logger = NULL;
}
}
void stdout_logger(int loglevel, const char* buf, int len) {
fprintf(stdout, "%.*s", len, buf);
}
void stderr_logger(int loglevel, const char* buf, int len) {
fprintf(stderr, "%.*s", len, buf);
}
void file_logger(int loglevel, const char* buf, int len) {
logfile_write(hv_default_logger(), buf, len);
}
================================================
FILE: base/hlog.h
================================================
#ifndef HV_LOG_H_
#define HV_LOG_H_
/*
* hlog is thread-safe
*/
#include <string.h>
#ifdef _WIN32
#define DIR_SEPARATOR '\\'
#define DIR_SEPARATOR_STR "\\"
#else
#define DIR_SEPARATOR '/'
#define DIR_SEPARATOR_STR "/"
#endif
#ifndef __FILENAME__
// #define __FILENAME__ (strrchr(__FILE__, DIR_SEPARATOR) ? strrchr(__FILE__, DIR_SEPARATOR) + 1 : __FILE__)
#define __FILENAME__ (strrchr(DIR_SEPARATOR_STR __FILE__, DIR_SEPARATOR) + 1)
#endif
#include "hexport.h"
#ifdef __cplusplus
extern "C" {
#endif
#define CLR_CLR "\033[0m" /* 恢复颜色 */
#define CLR_BLACK "\033[30m" /* 黑色字 */
#define CLR_RED "\033[31m" /* 红色字 */
#define CLR_GREEN "\033[32m" /* 绿色字 */
#define CLR_YELLOW "\033[33m" /* 黄色字 */
#define CLR_BLUE "\033[34m" /* 蓝色字 */
#define CLR_PURPLE "\033[35m" /* 紫色字 */
#define CLR_SKYBLUE "\033[36m" /* 天蓝字 */
#define CLR_WHITE "\033[37m" /* 白色字 */
#define CLR_BLK_WHT "\033[40;37m" /* 黑底白字 */
#define CLR_RED_WHT "\033[41;37m" /* 红底白字 */
#define CLR_GREEN_WHT "\033[42;37m" /* 绿底白字 */
#define CLR_YELLOW_WHT "\033[43;37m" /* 黄底白字 */
#define CLR_BLUE_WHT "\033[44;37m" /* 蓝底白字 */
#define CLR_PURPLE_WHT "\033[45;37m" /* 紫底白字 */
#define CLR_SKYBLUE_WHT "\033[46;37m" /* 天蓝底白字 */
#define CLR_WHT_BLK "\033[47;30m" /* 白底黑字 */
// XXX(id, str, clr)
#define LOG_LEVEL_MAP(XXX) \
XXX(LOG_LEVEL_DEBUG, "DEBUG", CLR_WHITE) \
XXX(LOG_LEVEL_INFO, "INFO ", CLR_GREEN) \
XXX(LOG_LEVEL_WARN, "WARN ", CLR_YELLOW) \
XXX(LOG_LEVEL_ERROR, "ERROR", CLR_RED) \
XXX(LOG_LEVEL_FATAL, "FATAL", CLR_RED_WHT)
typedef enum {
LOG_LEVEL_VERBOSE = 0,
#define XXX(id, str, clr) id,
LOG_LEVEL_MAP(XXX)
#undef XXX
LOG_LEVEL_SILENT
} log_level_e;
#define DEFAULT_LOG_FILE "libhv"
#define DEFAULT_LOG_LEVEL LOG_LEVEL_INFO
#define DEFAULT_LOG_FORMAT "%y-%m-%d %H:%M:%S.%z %L %s"
#define DEFAULT_LOG_REMAIN_DAYS 1
#define DEFAULT_LOG_MAX_BUFSIZE (1<<14) // 16k
#define DEFAULT_LOG_MAX_FILESIZE (1<<24) // 16M
#define DEFAULT_LOG_TRUNCATE_PERCENT 0.99f // truncate when exceeded max filesize
// logger: default file_logger
// network_logger() see event/nlog.h
typedef void (*logger_handler)(int loglevel, const char* buf, int len);
HV_EXPORT void stdout_logger(int loglevel, const char* buf, int len);
HV_EXPORT void stderr_logger(int loglevel, const char* buf, int len);
HV_EXPORT void file_logger(int loglevel, const char* buf, int len);
// network_logger implement see event/nlog.h
// HV_EXPORT void network_logger(int loglevel, const char* buf, int len);
typedef struct logger_s logger_t;
HV_EXPORT logger_t* logger_create();
HV_EXPORT void logger_destroy(logger_t* logger);
HV_EXPORT void logger_set_handler(logger_t* logger, logger_handler fn);
HV_EXPORT void logger_set_level(logger_t* logger, int level);
// level = [VERBOSE,DEBUG,INFO,WARN,ERROR,FATAL,SILENT]
HV_EXPORT void logger_set_level_by_str(logger_t* logger, const char* level);
/*
* format = "%y-%m-%d %H:%M:%S.%z %L %s"
* message = "2020-01-02 03:04:05.067 DEBUG message"
* %y year
* %m month
* %d day
* %H hour
* %M min
* %S sec
* %z ms
* %Z us
* %l First character of level
* %L All characters of level
* %s message
* %% %
*/
HV_EXPORT void logger_set_format(logger_t* logger, const char* format);
HV_EXPORT void logger_set_max_bufsize(logger_t* logger, unsigned int bufsize);
HV_EXPORT void logger_enable_color(logger_t* logger, int on);
HV_EXPORT int logger_print(logger_t* logger, int level, const char* fmt, ...);
// below for file logger
HV_EXPORT void logger_set_file(logger_t* logger, const char* filepath);
HV_EXPORT void logger_set_max_filesize(logger_t* logger, unsigned long long filesize);
// 16, 16M, 16MB
HV_EXPORT void logger_set_max_filesize_by_str(logger_t* logger, const char* filesize);
HV_EXPORT void logger_set_remain_days(logger_t* logger, int days);
HV_EXPORT void logger_set_truncate_percent(logger_t* logger, float percent);
HV_EXPORT void logger_enable_fsync(logger_t* logger, int on);
HV_EXPORT void logger_fsync(logger_t* logger);
HV_EXPORT const char* logger_get_cur_file(logger_t* logger);
// hlog: default logger instance
HV_EXPORT logger_t* hv_default_logger();
HV_EXPORT void hv_destroy_default_logger(void);
// macro hlog*
#define hlog hv_default_logger()
#define hlog_destory() hv_destroy_default_logger()
#define hlog_disable() logger_set_level(hlog, LOG_LEVEL_SILENT)
#define hlog_set_file(filepath) logger_set_file(hlog, filepath)
#define hlog_set_level(level) logger_set_level(hlog, level)
#define hlog_set_level_by_str(level) logger_set_level_by_str(hlog, level)
#define hlog_set_handler(fn) logger_set_handler(hlog, fn)
#define hlog_set_format(format) logger_set_format(hlog, format)
#define hlog_set_max_filesize(filesize) logger_set_max_filesize(hlog, filesize)
#define hlog_set_max_filesize_by_str(filesize) logger_set_max_filesize_by_str(hlog, filesize)
#define hlog_set_remain_days(days) logger_set_remain_days(hlog, days)
#define hlog_set_truncate_percent(val) logger_set_truncate_percent(hlog, val)
#define hlog_enable_fsync() logger_enable_fsync(hlog, 1)
#define hlog_disable_fsync() logger_enable_fsync(hlog, 0)
#define hlog_fsync() logger_fsync(hlog)
#define hlog_get_cur_file() logger_get_cur_file(hlog)
#define hlogd(fmt, ...) logger_print(hlog, LOG_LEVEL_DEBUG, fmt " [%s:%d:%s]", ## __VA_ARGS__, __FILENAME__, __LINE__, __FUNCTION__)
#define hlogi(fmt, ...) logger_print(hlog, LOG_LEVEL_INFO, fmt " [%s:%d:%s]", ## __VA_ARGS__, __FILENAME__, __LINE__, __FUNCTION__)
#define hlogw(fmt, ...) logger_print(hlog, LOG_LEVEL_WARN, fmt " [%s:%d:%s]", ## __VA_ARGS__, __FILENAME__, __LINE__, __FUNCTION__)
#define hloge(fmt, ...) logger_print(hlog, LOG_LEVEL_ERROR, fmt " [%s:%d:%s]", ## __VA_ARGS__, __FILENAME__, __LINE__, __FUNCTION__)
#define hlogf(fmt, ...) logger_print(hlog, LOG_LEVEL_FATAL, fmt " [%s:%d:%s]", ## __VA_ARGS__, __FILENAME__, __LINE__, __FUNCTION__)
// below for android
#if defined(ANDROID) || defined(__ANDROID__)
#include <android/log.h>
#define LOG_TAG "JNI"
#undef hlogd
#undef hlogi
#undef hlogw
#undef hloge
#undef hlogf
#define hlogd(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define hlogi(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define hlogw(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#define hloge(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define hlogf(...) __android_log_print(ANDROID_LOG_FATAL, LOG_TAG, __VA_ARGS__)
#endif
// macro alias
#if !defined(LOGD) && !defined(LOGI) && !defined(LOGW) && !defined(LOGE) && !defined(LOGF)
#define LOGD hlogd
#define LOGI hlogi
#define LOGW hlogw
#define LOGE hloge
#define LOGF hlogf
#endif
#ifdef __cplusplus
} // extern "C"
#endif
#endif // HV_LOG_H_
================================================
FILE: base/hmain.c
================================================
#include "hmain.h"
#include "hbase.h"
#include "hlog.h"
#include "herr.h"
#include "htime.h"
#include "hthread.h"
#ifdef OS_DARWIN
#include <crt_externs.h>
#define environ (*_NSGetEnviron())
#endif
main_ctx_t g_main_ctx;
printf_t printf_fn = printf;
static void init_arg_kv(int maxsize) {
g_main_ctx.arg_kv_size = 0;
SAFE_ALLOC(g_main_ctx.arg_kv, sizeof(char*) * maxsize);
}
static void save_arg_kv(const char* key, int key_len, const char* val, int val_len) {
if (key_len <= 0) key_len = strlen(key);
if (val_len <= 0) val_len = strlen(val);
char* arg = NULL;
SAFE_ALLOC(arg, key_len + val_len + 2);
memcpy(arg, key, key_len);
arg[key_len] = '=';
memcpy(arg + key_len + 1, val, val_len);
// printf("save_arg_kv: %s\n", arg);
g_main_ctx.arg_kv[g_main_ctx.arg_kv_size++] = arg;
}
static void init_arg_list(int maxsize) {
g_main_ctx.arg_list_size = 0;
SAFE_ALLOC(g_main_ctx.arg_list, sizeof(char*) * maxsize);
}
static void save_arg_list(const char* arg) {
// printf("save_arg_list: %s\n", arg);
g_main_ctx.arg_list[g_main_ctx.arg_list_size++] = strdup(arg);
}
static const char* get_val(char** kvs, const char* key) {
if (kvs == NULL) return NULL;
int key_len = strlen(key);
char* kv = NULL;
int kv_len = 0;
for (int i = 0; kvs[i]; ++i) {
kv = kvs[i];
kv_len = strlen(kv);
if (kv_len <= key_len) continue;
// key=val
if (memcmp(kv, key, key_len) == 0 && kv[key_len] == '=') {
return kv + key_len + 1;
}
}
return NULL;
}
const char* get_arg(const char* key) {
return get_val(g_main_ctx.arg_kv, key);
}
const char* get_env(const char* key) {
return get_val(g_main_ctx.save_envp, key);
}
int main_ctx_init(int argc, char** argv) {
if (argc == 0 || argv == NULL) {
argc = 1;
SAFE_ALLOC(argv, 2 * sizeof(char*));
SAFE_ALLOC(argv[0], MAX_PATH);
get_executable_path(argv[0], MAX_PATH);
}
get_run_dir(g_main_ctx.run_dir, sizeof(g_main_ctx.run_dir));
//printf("run_dir=%s\n", g_main_ctx.run_dir);
strncpy(g_main_ctx.program_name, hv_basename(argv[0]), sizeof(g_main_ctx.program_name));
#ifdef OS_WIN
if (strcmp(g_main_ctx.program_name+strlen(g_main_ctx.program_name)-4, ".exe") == 0) {
*(g_main_ctx.program_name+strlen(g_main_ctx.program_name)-4) = '\0';
}
#endif
//printf("program_name=%s\n", g_main_ctx.program_name);
char logdir[MAX_PATH] = {0};
snprintf(logdir, sizeof(logdir), "%s/logs", g_main_ctx.run_dir);
hv_mkdir(logdir);
snprintf(g_main_ctx.confile, sizeof(g_main_ctx.confile), "%s/etc/%s.conf", g_main_ctx.run_dir, g_main_ctx.program_name);
snprintf(g_main_ctx.pidfile, sizeof(g_main_ctx.pidfile), "%s/logs/%s.pid", g_main_ctx.run_dir, g_main_ctx.program_name);
snprintf(g_main_ctx.logfile, sizeof(g_main_ctx.logfile), "%s/logs/%s.log", g_main_ctx.run_dir, g_main_ctx.program_name);
hlog_set_file(g_main_ctx.logfile);
g_main_ctx.pid = getpid();
g_main_ctx.oldpid = getpid_from_pidfile();
#ifdef OS_UNIX
if (kill(g_main_ctx.oldpid, 0) == -1 && errno == ESRCH) {
g_main_ctx.oldpid = -1;
}
#else
HANDLE hproc = OpenProcess(PROCESS_TERMINATE, FALSE, g_main_ctx.oldpid);
if (hproc == NULL) {
g_main_ctx.oldpid = -1;
}
else {
CloseHandle(hproc);
}
#endif
// save arg
int i = 0;
g_main_ctx.os_argv = argv;
g_main_ctx.argc = 0;
g_main_ctx.arg_len = 0;
for (i = 0; argv[i]; ++i) {
g_main_ctx.arg_len += strlen(argv[i]) + 1;
}
g_main_ctx.argc = i;
char* argp = NULL;
SAFE_ALLOC(argp, g_main_ctx.arg_len);
SAFE_ALLOC(g_main_ctx.save_argv, (g_main_ctx.argc + 1) * sizeof(char*));
char* cmdline = NULL;
SAFE_ALLOC(cmdline, g_main_ctx.arg_len);
g_main_ctx.cmdline = cmdline;
for (i = 0; argv[i]; ++i) {
strcpy(argp, argv[i]);
g_main_ctx.save_argv[i] = argp;
argp += strlen(argv[i]) + 1;
strcpy(cmdline, argv[i]);
cmdline += strlen(argv[i]);
*cmdline = ' ';
++cmdline;
}
g_main_ctx.save_argv[g_main_ctx.argc] = NULL;
g_main_ctx.cmdline[g_main_ctx.arg_len-1] = '\0';
#if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_DARWIN)
// save env
g_main_ctx.os_envp = environ;
g_main_ctx.envc = 0;
g_main_ctx.env_len = 0;
for (i = 0; environ[i]; ++i) {
g_main_ctx.env_len += strlen(environ[i]) + 1;
}
g_main_ctx.envc = i;
char* envp = NULL;
SAFE_ALLOC(envp, g_main_ctx.env_len);
SAFE_ALLOC(g_main_ctx.save_envp, (g_main_ctx.envc + 1) * sizeof(char*));
for (i = 0; environ[i]; ++i) {
g_main_ctx.save_envp[i] = envp;
strcpy(g_main_ctx.save_envp[i], environ[i]);
envp += strlen(environ[i]) + 1;
}
g_main_ctx.save_envp[g_main_ctx.envc] = NULL;
#endif
// signals
g_main_ctx.reload_fn = NULL;
g_main_ctx.reload_userdata = NULL;
// master workers
g_main_ctx.worker_processes = 0;
g_main_ctx.worker_threads = 0;
g_main_ctx.worker_fn = 0;
g_main_ctx.worker_userdata = 0;
g_main_ctx.proc_ctxs = NULL;
atexit(main_ctx_free);
return 0;
}
void main_ctx_free(void) {
if (g_main_ctx.save_argv) {
SAFE_FREE(g_main_ctx.save_argv[0]);
SAFE_FREE(g_main_ctx.save_argv);
}
SAFE_FREE(g_main_ctx.cmdline);
if (g_main_ctx.save_envp) {
SAFE_FREE(g_main_ctx.save_envp[0]);
SAFE_FREE(g_main_ctx.save_envp);
}
if (g_main_ctx.arg_kv) {
for (int i = 0; i < g_main_ctx.arg_kv_size; ++i) {
SAFE_FREE(g_main_ctx.arg_kv[i]);
}
SAFE_FREE(g_main_ctx.arg_kv);
}
if (g_main_ctx.arg_list) {
for (int i = 0; i < g_main_ctx.arg_list_size; ++i) {
SAFE_FREE(g_main_ctx.arg_list[i]);
}
SAFE_FREE(g_main_ctx.arg_list);
}
}
#define UNDEFINED_OPTION -1
static int get_arg_type(int short_opt, const char* options) {
if (options == NULL) return UNDEFINED_OPTION;
const char* p = options;
while (*p && *p != short_opt) ++p;
if (*p == '\0') return UNDEFINED_OPTION;
if (*(p+1) == ':') return REQUIRED_ARGUMENT;
return NO_ARGUMENT;
}
int parse_opt(int argc, char** argv, const char* options) {
if (argc < 1) return 0;
init_arg_kv(strlen(options) + 1);
init_arg_list(argc);
for (int i = 1; argv[i]; ++i) {
char* p = argv[i];
if (*p != '-') {
save_arg_list(argv[i]);
continue;
}
while (*++p) {
int arg_type = get_arg_type(*p, options);
if (arg_type == UNDEFINED_OPTION) {
printf_fn("Invalid option '%c'\n", *p);
return -20;
} else if (arg_type == NO_ARGUMENT) {
save_arg_kv(p, 1, OPTION_ENABLE, 0);
continue;
} else if (arg_type == REQUIRED_ARGUMENT) {
if (*(p+1) != '\0') {
save_arg_kv(p, 1, p+1, 0);
break;
} else if (argv[i+1] != NULL) {
save_arg_kv(p, 1, argv[++i], 0);
break;
} else {
printf_fn("Option '%c' requires param\n", *p);
return -30;
}
}
}
}
return 0;
}
static const option_t* get_option(const char* opt, const option_t* long_options, int size) {
if (opt == NULL || long_options == NULL) return NULL;
int len = strlen(opt);
if (len == 0) return NULL;
if (len == 1) {
for (int i = 0; i < size; ++i) {
if (long_options[i].short_opt == *opt) {
return &long_options[i];
}
}
} else {
for (int i = 0; i < size; ++i) {
if (strcmp(long_options[i].long_opt, opt) == 0) {
return &long_options[i];
}
}
}
return NULL;
}
#define MAX_OPTION 32
// opt type
#define NOPREFIX_OPTION 0
#define SHORT_OPTION -1
#define LONG_OPTION -2
int parse_opt_long(int argc, char** argv, const option_t* long_options, int size) {
if (argc < 1) return 0;
init_arg_kv(size + 1);
init_arg_list(argc);
char opt[MAX_OPTION+1] = {0};
for (int i = 1; argv[i]; ++i) {
char* arg = argv[i];
int opt_type = NOPREFIX_OPTION;
// prefix
if (*arg == OPTION_PREFIX) {
++arg;
opt_type = SHORT_OPTION;
if (*arg == OPTION_PREFIX) {
++arg;
opt_type = LONG_OPTION;
}
}
int arg_len = strlen(arg);
// delim
char* delim = strchr(arg, OPTION_DELIM);
if (delim) {
if (delim == arg || delim == arg+arg_len-1 || delim-arg > MAX_OPTION) {
printf_fn("Invalid option '%s'\n", argv[i]);
return -10;
}
memcpy(opt, arg, delim-arg);
opt[delim-arg] = '\0';
} else {
if (opt_type == SHORT_OPTION) {
*opt = *arg;
opt[1] = '\0';
} else {
strncpy(opt, arg, MAX_OPTION);
}
}
// get_option
const option_t* pOption = get_option(opt, long_options, size);
if (pOption == NULL) {
if (delim == NULL && opt_type == NOPREFIX_OPTION) {
save_arg_list(arg);
continue;
} else {
printf_fn("Invalid option: '%s'\n", argv[i]);
return -10;
}
}
const char* value = NULL;
if (pOption->arg_type == NO_ARGUMENT) {
// -h
value = OPTION_ENABLE;
} else {
if (delim) {
// --port=80
value = delim+1;
} else {
if (opt_type == SHORT_OPTION && *(arg+1) != '\0') {
// p80
value = arg+1;
} else if (argv[i+1] != NULL) {
// --port 80
value = argv[++i];
} else if (pOption->arg_type == REQUIRED_ARGUMENT) {
printf_fn("Option '%s' requires parament\n", opt);
return -20;
} else {
// arg_type == OPTIONAL_ARGUMENT
value = OPTION_ENABLE;
}
}
}
// preferred to use short_opt as key
if (pOption->short_opt > 0) {
save_arg_kv(&pOption->short_opt, 1, value, 0);
} else if (pOption->long_opt) {
save_arg_kv(pOption->long_opt, 0, value, 0);
}
}
return 0;
}
int dump_opt_long(const option_t* long_options, int opt_size, char* out_str, int out_size) {
/*
* Usage: program_name [short_options]
* Options:
* -%c|--%s description
* -%c|--%s <value> description
* -%c|--%s [value] description
*/
int align = 0, max_align = 0;
char short_options[256] = {0};
char* p = short_options;
for (int i = 0; i < opt_size; ++i) {
if (long_options[i].short_opt > 0) {
*p++ = long_options[i].short_opt;
}
if (long_options[i].arg_type == NO_ARGUMENT) {
// " -%c|--%s "
align = 9 + strlen(long_options[i].long_opt);
} else {
// " -%c|--%s <value> "
align = 17 + strlen(long_options[i].long_opt);
if (long_options[i].short_opt > 0) {
*p++ = ':';
}
}
if (align > max_align) max_align = align;
}
int offset = 0;
if (*g_main_ctx.program_name) {
offset = snprintf(out_str, out_size, "Usage: %s [%s]\n", g_main_ctx.program_name, short_options);
}
offset += snprintf(out_str + offset, out_size - offset, "Options:\n");
char short_opt_chars[4] = {0};
for (int i = 0; i < opt_size; ++i) {
if (long_options[i].short_opt > 0) {
// -%c|
short_opt_chars[0] = '-';
short_opt_chars[1] = long_options[i].short_opt;
short_opt_chars[2] = '|';
} else {
short_opt_chars[0] = ' ';
short_opt_chars[1] = ' ';
short_opt_chars[2] = ' ';
}
if (long_options[i].arg_type == NO_ARGUMENT) {
// " -%c|--%s "
align = 9 + strlen(long_options[i].long_opt);
} else {
// " -%c|--%s <value> "
align = 17 + strlen(long_options[i].long_opt);
}
offset += snprintf(out_str + offset, out_size - offset, " %s--%s%s %*s%s\n",
short_opt_chars,
long_options[i].long_opt,
long_options[i].arg_type == REQUIRED_ARGUMENT ? " <value>" :
long_options[i].arg_type == OPTIONAL_ARGUMENT ? " [value]" : "",
max_align - align, "",
long_options[i].description ? long_options[i].description : "");
}
return offset;
}
#if defined(OS_UNIX) && !HAVE_SETPROCTITLE
/*
* memory layout
* argv[0]\0argv[1]\0argv[n]\0env[0]\0env[1]\0env[n]\0
*/
void setproctitle(const char* fmt, ...) {
char buf[256] = {0};
va_list ap;
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf) - 1, fmt, ap);
va_end(ap);
int len = g_main_ctx.arg_len + g_main_ctx.env_len;
if (g_main_ctx.os_argv && len) {
strncpy(g_main_ctx.os_argv[0], buf, len-1);
}
}
#endif
int create_pidfile() {
FILE* fp = fopen(g_main_ctx.pidfile, "w");
if (fp == NULL) {
hloge("fopen('%s') error: %d", g_main_ctx.pidfile, errno);
return -1;
}
g_main_ctx.pid = hv_getpid();
fprintf(fp, "%d\n", (int)g_main_ctx.pid);
fclose(fp);
hlogi("create_pidfile('%s') pid=%d", g_main_ctx.pidfile, g_main_ctx.pid);
atexit(delete_pidfile);
return 0;
}
void delete_pidfile(void) {
hlogi("delete_pidfile('%s') pid=%d", g_main_ctx.pidfile, g_main_ctx.pid);
remove(g_main_ctx.pidfile);
}
pid_t getpid_from_pidfile() {
FILE* fp = fopen(g_main_ctx.pidfile, "r");
if (fp == NULL) {
// hloge("fopen('%s') error: %d", g_main_ctx.pidfile, errno);
return -1;
}
int pid = -1;
fscanf(fp, "%d", &pid);
fclose(fp);
return pid;
}
#ifdef OS_UNIX
// unix use signal
#include <sys/wait.h>
void signal_handler(int signo) {
hlogi("pid=%d recv signo=%d", getpid(), signo);
switch (signo) {
case SIGINT:
case SIGNAL_TERMINATE:
hlogi("killall processes");
signal(SIGCHLD, SIG_IGN);
// master send SIGKILL => workers
for (int i = 0; i < g_main_ctx.worker_processes; ++i) {
if (g_main_ctx.proc_ctxs[i].pid <= 0) break;
kill(g_main_ctx.proc_ctxs[i].pid, SIGKILL);
g_main_ctx.proc_ctxs[i].pid = -1;
}
exit(0);
break;
case SIGCHLD:
{
pid_t pid = 0;
int status = 0;
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
hlogw("proc stop/waiting, pid=%d status=%d", pid, status);
for (int i = 0; i < g_main_ctx.worker_processes; ++i) {
proc_ctx_t* ctx = g_main_ctx.proc_ctxs + i;
if (ctx->pid == pid) {
ctx->pid = -1;
// NOTE: avoid frequent crash and restart
time_t run_time = time(NULL) - ctx->start_time;
if (ctx->spawn_cnt < 3 || run_time > 3600) {
hproc_spawn(ctx);
}
else {
hloge("proc crash, pid=%d spawn_cnt=%d run_time=%us",
pid, ctx->spawn_cnt, (unsigned int)run_time);
bool have_worker = false;
for (int i = 0; i < g_main_ctx.worker_processes; ++i) {
if (g_main_ctx.proc_ctxs[i].pid > 0) {
have_worker = true;
break;
}
}
if (!have_worker) {
hlogw("No alive worker process, exit master process!");
exit(0);
}
}
break;
}
}
}
}
break;
case SIGNAL_RELOAD:
if (g_main_ctx.reload_fn) {
g_main_ctx.reload_fn(g_main_ctx.reload_userdata);
if (getpid_from_pidfile() == getpid()) {
// master send SIGNAL_RELOAD => workers
for (int i = 0; i < g_main_ctx.worker_processes; ++i) {
if (g_main_ctx.proc_ctxs[i].pid <= 0) break;
kill(g_main_ctx.proc_ctxs[i].pid, SIGNAL_RELOAD);
}
}
}
break;
default:
break;
}
}
int signal_init(procedure_t reload_fn, void* reload_userdata) {
g_main_ctx.reload_fn = reload_fn;
g_main_ctx.reload_userdata = reload_userdata;
signal(SIGINT, signal_handler);
signal(SIGCHLD, signal_handler);
signal(SIGNAL_TERMINATE, signal_handler);
signal(SIGNAL_RELOAD, signal_handler);
return 0;
}
#elif defined(OS_WIN)
#include <mmsystem.h> // for timeSetEvent
// win32 use Event
static HANDLE s_hEventTerm = NULL;
static HANDLE s_hEventTermWait = NULL;
static HANDLE s_hEventReload = NULL;
static void WINAPI on_timer(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) {
DWORD ret;
ret = WaitForSingleObject(s_hEventTerm, 0);
if (ret == WAIT_OBJECT_0) {
hlogi("pid=%d recv event [TERM]", getpid());
if (getpid_from_pidfile() == getpid()) {
SetEvent(s_hEventTermWait);
timeKillEvent(uTimerID);
exit(0);
}
}
ret = WaitForSingleObject(s_hEventReload, 0);
if (ret == WAIT_OBJECT_0) {
hlogi("pid=%d recv event [RELOAD]", getpid());
if (g_main_ctx.reload_fn) {
g_main_ctx.reload_fn(g_main_ctx.reload_userdata);
}
}
}
static void signal_cleanup(void) {
CloseHandle(s_hEventTerm);
s_hEventTerm = NULL;
CloseHandle(s_hEventTermWait);
s_hEventTermWait = NULL;
CloseHandle(s_hEventReload);
s_hEventReload = NULL;
}
int signal_init(procedure_t reload_fn, void* reload_userdata) {
g_main_ctx.reload_fn = reload_fn;
g_main_ctx.reload_userdata = reload_userdata;
char eventname[MAX_PATH] = {0};
snprintf(eventname, sizeof(eventname), "%s_term_event", g_main_ctx.program_name);
s_hEventTerm = CreateEvent(NULL, FALSE, FALSE, eventname);
if(s_hEventTerm == NULL) return -1;
snprintf(eventname, sizeof(eventname), "%s_term_wait_event", g_main_ctx.program_name);
s_hEventTermWait = CreateEvent(NULL, FALSE, FALSE, eventname);
if(s_hEventTermWait == NULL) return -2;
snprintf(eventname, sizeof(eventname), "%s_reload_event", g_main_ctx.program_name);
s_hEventReload = CreateEvent(NULL, FALSE, FALSE, eventname);
if(s_hEventReload == NULL) return -3;
timeSetEvent(1000, 1000, on_timer, 0, TIME_PERIODIC);
atexit(signal_cleanup);
return 0;
}
#endif
static void kill_proc(int pid) {
#ifdef OS_UNIX
kill(pid, SIGNAL_TERMINATE);
#else
SetEvent(s_hEventTerm);
if (WaitForSingleObject(s_hEventTermWait, 2000) == WAIT_OBJECT_0) return;
HANDLE hproc = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
if (hproc) {
TerminateProcess(hproc, 0);
CloseHandle(hproc);
}
#endif
}
void signal_handle(const char* signal) {
if (signal_handle_noexit(signal)) exit(0);
}
bool signal_handle_noexit(const char* signal) {
if (strcmp(signal, "start") == 0) {
if (g_main_ctx.oldpid > 0) {
printf_fn("%s is already running, pid=%d\n", g_main_ctx.program_name, g_main_ctx.oldpid);
return true;
}
} else if (strcmp(signal, "stop") == 0) {
if (g_main_ctx.oldpid > 0) {
kill_proc(g_main_ctx.oldpid);
printf_fn("%s stop/waiting\n", g_main_ctx.program_name);
} else {
printf_fn("%s is already stopped\n", g_main_ctx.program_name);
}
return true;
} else if (strcmp(signal, "restart") == 0) {
if (g_main_ctx.oldpid > 0) {
kill_proc(g_main_ctx.oldpid);
printf_fn("%s stop/waiting\n", g_main_ctx.program_name);
hv_sleep(1);
}
} else if (strcmp(signal, "status") == 0) {
if (g_main_ctx.oldpid > 0) {
printf_fn("%s start/running, pid=%d\n", g_main_ctx.program_name, g_main_ctx.oldpid);
} else {
printf_fn("%s is already stopped\n", g_main_ctx.program_name);
}
return true;
} else if (strcmp(signal, "reload") == 0) {
if (g_main_ctx.oldpid > 0) {
printf_fn("reload confile [%s]\n", g_main_ctx.confile);
#ifdef OS_UNIX
kill(g_main_ctx.oldpid, SIGNAL_RELOAD);
#else
SetEvent(s_hEventReload);
#endif
hv_sleep(1);
} else {
printf_fn("%s is already stopped\n", g_main_ctx.program_name);
}
return true;
} else {
printf_fn("Invalid signal: '%s'\n", signal);
return true;
}
printf_fn("%s start/running\n", g_main_ctx.program_name);
return false;
}
// master-workers processes
static HTHREAD_ROUTINE(worker_thread) {
hlogi("worker_thread pid=%ld tid=%ld", hv_getpid(), hv_gettid());
if (g_main_ctx.worker_fn) {
g_main_ctx.worker_fn(g_main_ctx.worker_userdata);
}
return 0;
}
static void worker_init(void* userdata) {
#ifdef OS_UNIX
setproctitle("%s: worker process", g_main_ctx.program_name);
signal(SIGNAL_RELOAD, signal_handler);
#endif
}
static void worker_proc(void* userdata) {
for (int i = 1; i < g_main_ctx.worker_threads; ++i) {
hthread_create(worker_thread, NULL);
}
worker_thread(NULL);
}
int master_workers_run(procedure_t worker_fn, void* worker_userdata,
int worker_processes, int worker_threads, bool wait) {
#ifdef OS_WIN
// NOTE: Windows not provide MultiProcesses
if (worker_threads == 0) {
// MultiProcesses => MultiThreads
worker_threads = worker_processes;
}
worker_processes = 0;
#endif
if (worker_threads == 0) worker_threads = 1;
g_main_ctx.worker_threads = worker_threads;
g_main_ctx.worker_fn = worker_fn;
g_main_ctx.worker_userdata = worker_userdata;
if (worker_processes == 0) {
// single process
if (wait) {
for (int i = 1; i < worker_threads; ++i) {
hthread_create(worker_thread, NULL);
}
worker_thread(NULL);
}
else {
for (int i = 0; i < worker_threads; ++i) {
hthread_create(worker_thread, NULL);
}
}
}
else {
if (g_main_ctx.worker_processes != 0) {
return ERR_OVER_LIMIT;
}
// master-workers processes
#ifdef OS_UNIX
setproctitle("%s: master process", g_main_ctx.program_name);
signal(SIGNAL_RELOAD, signal_handler);
#endif
g_main_ctx.worker_processes = worker_processes;
int bytes = g_main_ctx.worker_processes * sizeof(proc_ctx_t);
SAFE_ALLOC(g_main_ctx.proc_ctxs, bytes);
proc_ctx_t* ctx = g_main_ctx.proc_ctxs;
for (int i = 0; i < g_main_ctx.worker_processes; ++i, ++ctx) {
ctx->init = worker_init;
ctx->proc = worker_proc;
hproc_spawn(ctx);
hlogi("workers[%d] start/running, pid=%d", i, ctx->pid);
}
g_main_ctx.pid = getpid();
hlogi("master start/running, pid=%d", g_main_ctx.pid);
if (wait) {
while (1) hv_sleep (1);
}
}
return 0;
}
================================================
FILE: base/hmain.h
================================================
#ifndef HV_MAIN_H_
#define HV_MAIN_H_
#include "hexport.h"
#include "hplatform.h"
#include "hdef.h"
#include "hproc.h"
#ifdef _MSC_VER
#pragma comment(lib, "winmm.lib") // for timeSetEvent
#endif
BEGIN_EXTERN_C
typedef int (*printf_t)(const char *const fmt, ...);
typedef struct main_ctx_s {
char run_dir[MAX_PATH];
char program_name[MAX_PATH];
char confile[MAX_PATH]; // default etc/${program}.conf
char pidfile[MAX_PATH]; // default logs/${program}.pid
char logfile[MAX_PATH]; // default logs/${program}.log
pid_t pid; // getpid
pid_t oldpid; // getpid_from_pidfile
// arg
int argc;
int arg_len;
char** os_argv;
char** save_argv;
char* cmdline;
// parsed arg
int arg_kv_size;
char** arg_kv;
int arg_list_size;
char** arg_list;
// env
int envc;
int env_len;
char** os_envp;
char** save_envp;
// signals
procedure_t reload_fn;
void* reload_userdata;
// master workers model
int worker_processes;
int worker_threads;
procedure_t worker_fn;
void* worker_userdata;
proc_ctx_t* proc_ctxs;
} main_ctx_t;
// arg_type
#define NO_ARGUMENT 0
#define REQUIRED_ARGUMENT 1
#define OPTIONAL_ARGUMENT 2
// option define
#define OPTION_PREFIX '-'
#define OPTION_DELIM '='
#define OPTION_ENABLE "1"
#define OPTION_DISABLE "0"
typedef struct option_s {
char short_opt;
const char* long_opt;
int arg_type;
const char* description;
} option_t;
HV_EXPORT int main_ctx_init(int argc, char** argv);
HV_EXPORT void main_ctx_free(void);
// ls -a -l
// ls -al
// watch -n 10 ls
// watch -n10 ls
HV_EXPORT int parse_opt(int argc, char** argv, const char* opt);
// gcc -g -Wall -O3 -std=cpp main.c
HV_EXPORT int parse_opt_long(int argc, char** argv, const option_t* long_options, int opt_size);
HV_EXPORT int dump_opt_long(const option_t* long_options, int opt_size, char* out_str, int out_size);
HV_EXPORT const char* get_arg(const char* key);
HV_EXPORT const char* get_env(const char* key);
#if defined(OS_UNIX) && !HAVE_SETPROCTITLE
HV_EXPORT void setproctitle(const char* fmt, ...);
#endif
// pidfile
HV_EXPORT int create_pidfile();
HV_EXPORT void delete_pidfile(void);
HV_EXPORT pid_t getpid_from_pidfile();
// signal=[start,stop,restart,status,reload]
HV_EXPORT int signal_init(procedure_t reload_fn DEFAULT(NULL), void* reload_userdata DEFAULT(NULL));
HV_EXPORT void signal_handle(const char* signal);
HV_EXPORT bool signal_handle_noexit(const char* signal);
#ifdef OS_UNIX
// we use SIGTERM to quit process, SIGUSR1 to reload confile
#define SIGNAL_TERMINATE SIGTERM
#define SIGNAL_RELOAD SIGUSR1
void signal_handler(int signo);
#endif
// global var
#define DEFAULT_WORKER_PROCESSES 4
#define MAXNUM_WORKER_PROCESSES 256
HV_EXPORT extern main_ctx_t g_main_ctx;
HV_EXPORT extern printf_t printf_fn;
// master-workers processes
HV_EXPORT int master_workers_run(
procedure_t worker_fn,
void* worker_userdata DEFAULT(NULL),
int worker_processes DEFAULT(DEFAULT_WORKER_PROCESSES),
int worker_threads DEFAULT(0),
bool wait DEFAULT(true));
END_EXTERN_C
#endif // HV_MAIN_H_
================================================
FILE: base/hmath.h
================================================
#ifndef HV_MATH_H_
#define HV_MATH_H_
#include <math.h>
static inline unsigned long floor2e(unsigned long num) {
unsigned long n = num;
int e = 0;
while (n>>=1) ++e;
unsigned long ret = 1;
while (e--) ret<<=1;
return ret;
}
static inline unsigned long ceil2e(unsigned long num) {
// 2**0 = 1
if (num == 0 || num == 1) return 1;
unsigned long n = num - 1;
int e = 1;
while (n>>=1) ++e;
unsigned long ret = 1;
while (e--) ret<<=1;
return ret;
}
// varint
gitextract_3mi7bcus/
├── .bazelrc
├── .clang-format
├── .gitattributes
├── .github/
│ └── workflows/
│ ├── CI.yml
│ └── benchmark.yml
├── .gitignore
├── .travis.yml
├── BUILD.bazel
├── BUILD.md
├── CMakeLists.txt
├── LICENSE
├── Makefile
├── Makefile.in
├── Makefile.vars
├── README-CN.md
├── README.md
├── TREE.md
├── WORKSPACE.bazel
├── base/
│ ├── README.md
│ ├── array.h
│ ├── hatomic.h
│ ├── hbase.c
│ ├── hbase.h
│ ├── hbuf.h
│ ├── hdef.h
│ ├── heap.h
│ ├── hendian.h
│ ├── herr.c
│ ├── herr.h
│ ├── hlog.c
│ ├── hlog.h
│ ├── hmain.c
│ ├── hmain.h
│ ├── hmath.h
│ ├── hmutex.h
│ ├── hplatform.h
│ ├── hproc.h
│ ├── hsocket.c
│ ├── hsocket.h
│ ├── hsysinfo.h
│ ├── hthread.h
│ ├── htime.c
│ ├── htime.h
│ ├── hversion.c
│ ├── hversion.h
│ ├── list.h
│ ├── netinet.h
│ ├── queue.h
│ ├── rbtree.c
│ └── rbtree.h
├── cert/
│ ├── cacert.pem
│ ├── gen.sh
│ ├── server.crt
│ └── server.key
├── cmake/
│ ├── ios.toolchain.cmake
│ ├── libhvConfig.cmake
│ ├── utils.cmake
│ └── vars.cmake
├── config.ini
├── configure
├── cpputil/
│ ├── LRUCache.h
│ ├── RAII.cpp
│ ├── README.md
│ ├── ThreadLocalStorage.cpp
│ ├── ThreadLocalStorage.h
│ ├── hasync.cpp
│ ├── hasync.h
│ ├── hdir.cpp
│ ├── hdir.h
│ ├── hfile.h
│ ├── hmap.h
│ ├── hobjectpool.h
│ ├── hpath.cpp
│ ├── hpath.h
│ ├── hscope.h
│ ├── hstring.cpp
│ ├── hstring.h
│ ├── hthreadpool.h
│ ├── hurl.cpp
│ ├── hurl.h
│ ├── ifconfig.cpp
│ ├── ifconfig.h
│ ├── iniparser.cpp
│ ├── iniparser.h
│ ├── json.hpp
│ └── singleton.h
├── docs/
│ ├── API.md
│ ├── PLAN.md
│ └── cn/
│ ├── Channel.md
│ ├── EventLoop.md
│ ├── HttpClient.md
│ ├── HttpContext.md
│ ├── HttpMessage.md
│ ├── HttpServer.md
│ ├── README.md
│ ├── TcpClient.md
│ ├── TcpServer.md
│ ├── UdpClient.md
│ ├── UdpServer.md
│ ├── WebSocketClient.md
│ ├── WebSocketServer.md
│ ├── hbase.md
│ ├── hlog.md
│ └── hloop.md
├── echo-servers/
│ ├── asio_echo.cpp
│ ├── benchmark.sh
│ ├── build.sh
│ ├── libev_echo.c
│ ├── libevent_echo.c
│ ├── libhv_echo.c
│ ├── libuv_echo.c
│ ├── muduo_echo.cpp
│ ├── pingpong_client.cpp
│ └── poco_echo.cpp
├── etc/
│ ├── hmain_test.conf
│ ├── httpd.conf
│ └── nginx.conf
├── event/
│ ├── README.md
│ ├── epoll.c
│ ├── evport.c
│ ├── hevent.c
│ ├── hevent.h
│ ├── hloop.c
│ ├── hloop.h
│ ├── io_uring.c
│ ├── iocp.c
│ ├── iowatcher.h
│ ├── kcp/
│ │ ├── LICENSE
│ │ ├── hkcp.c
│ │ ├── hkcp.h
│ │ ├── ikcp.c
│ │ └── ikcp.h
│ ├── kqueue.c
│ ├── nio.c
│ ├── nlog.c
│ ├── nlog.h
│ ├── noevent.c
│ ├── overlapio.c
│ ├── overlapio.h
│ ├── poll.c
│ ├── rudp.c
│ ├── rudp.h
│ ├── select.c
│ ├── unpack.c
│ ├── unpack.h
│ └── wepoll/
│ ├── LICENSE
│ ├── README.md
│ ├── wepoll.c
│ └── wepoll.h
├── evpp/
│ ├── Buffer.h
│ ├── Channel.h
│ ├── Event.h
│ ├── EventLoop.h
│ ├── EventLoopThread.h
│ ├── EventLoopThreadPool.h
│ ├── EventLoopThreadPool_test.cpp
│ ├── EventLoopThread_test.cpp
│ ├── EventLoop_test.cpp
│ ├── README.md
│ ├── Status.h
│ ├── TcpClient.h
│ ├── TcpClientEventLoop_test.cpp
│ ├── TcpClient_test.cpp
│ ├── TcpServer.h
│ ├── TcpServer_test.cpp
│ ├── TimerThread.h
│ ├── TimerThread_test.cpp
│ ├── UdpClient.h
│ ├── UdpClient_test.cpp
│ ├── UdpServer.h
│ ├── UdpServer_test.cpp
│ └── build_test.sh
├── examples/
│ ├── BUILD.bazel
│ ├── CMakeLists.txt
│ ├── README.md
│ ├── consul/
│ │ ├── consul.cpp
│ │ ├── consul.h
│ │ └── main.cpp
│ ├── curl.cpp
│ ├── hloop_test.c
│ ├── hmain_test.cpp
│ ├── htimer_test.c
│ ├── http_client_test.cpp
│ ├── http_server_test.cpp
│ ├── httpd/
│ │ ├── handler.cpp
│ │ ├── handler.h
│ │ ├── httpd.cpp
│ │ ├── router.cpp
│ │ └── router.h
│ ├── jsonrpc/
│ │ ├── cJSON.c
│ │ ├── cJSON.h
│ │ ├── handler.h
│ │ ├── jsonrpc_client.c
│ │ ├── jsonrpc_server.c
│ │ └── router.h
│ ├── kcptun/
│ │ ├── README.md
│ │ ├── client/
│ │ │ └── main.cpp
│ │ ├── server/
│ │ │ └── main.cpp
│ │ └── smux/
│ │ ├── smux.cpp
│ │ └── smux.h
│ ├── mqtt/
│ │ ├── mqtt_client_test.cpp
│ │ ├── mqtt_pub.c
│ │ └── mqtt_sub.c
│ ├── multi-thread/
│ │ ├── multi-acceptor-processes.c
│ │ ├── multi-acceptor-threads.c
│ │ └── one-acceptor-multi-workers.c
│ ├── nc.c
│ ├── nmap/
│ │ ├── main.cpp
│ │ ├── nmap.cpp
│ │ └── nmap.h
│ ├── pipe_test.c
│ ├── protorpc/
│ │ ├── handler/
│ │ │ ├── calc.h
│ │ │ ├── handler.h
│ │ │ └── login.h
│ │ ├── proto/
│ │ │ ├── base.proto
│ │ │ ├── calc.proto
│ │ │ ├── login.proto
│ │ │ └── protoc.sh
│ │ ├── protorpc.c
│ │ ├── protorpc.h
│ │ ├── protorpc_client.cpp
│ │ ├── protorpc_server.cpp
│ │ └── router.h
│ ├── socks5_proxy_server.c
│ ├── tcp_chat_server.c
│ ├── tcp_client_test.c
│ ├── tcp_echo_server.c
│ ├── tcp_proxy_server.c
│ ├── tinyhttpd.c
│ ├── tinyproxyd.c
│ ├── udp_echo_server.c
│ ├── udp_proxy_server.c
│ ├── websocket_client_test.cpp
│ ├── websocket_server_test.cpp
│ ├── wget.cpp
│ └── wrk.cpp
├── getting_started.sh
├── hconfig.h.in
├── hexport.h
├── html/
│ ├── EventSource.html
│ ├── WebSocket.html
│ ├── downloads/
│ │ └── 中文.html
│ ├── error.html
│ ├── index.html
│ └── 中文路径/
│ └── 中文名称.txt
├── http/
│ ├── Http1Parser.cpp
│ ├── Http1Parser.h
│ ├── Http2Parser.cpp
│ ├── Http2Parser.h
│ ├── HttpMessage.cpp
│ ├── HttpMessage.h
│ ├── HttpParser.cpp
│ ├── HttpParser.h
│ ├── README.md
│ ├── WebSocketChannel.cpp
│ ├── WebSocketChannel.h
│ ├── WebSocketParser.cpp
│ ├── WebSocketParser.h
│ ├── client/
│ │ ├── AsyncHttpClient.cpp
│ │ ├── AsyncHttpClient.h
│ │ ├── HttpClient.cpp
│ │ ├── HttpClient.h
│ │ ├── WebSocketClient.cpp
│ │ ├── WebSocketClient.h
│ │ ├── axios.h
│ │ └── requests.h
│ ├── grpcdef.h
│ ├── http2def.h
│ ├── http_content.cpp
│ ├── http_content.h
│ ├── http_parser.c
│ ├── http_parser.h
│ ├── httpdef.c
│ ├── httpdef.h
│ ├── multipart_parser.c
│ ├── multipart_parser.h
│ ├── server/
│ │ ├── FileCache.cpp
│ │ ├── FileCache.h
│ │ ├── HttpContext.h
│ │ ├── HttpHandler.cpp
│ │ ├── HttpHandler.h
│ │ ├── HttpMiddleware.cpp
│ │ ├── HttpMiddleware.h
│ │ ├── HttpResponseWriter.cpp
│ │ ├── HttpResponseWriter.h
│ │ ├── HttpServer.cpp
│ │ ├── HttpServer.h
│ │ ├── HttpService.cpp
│ │ ├── HttpService.h
│ │ ├── WebSocketServer.h
│ │ ├── http_page.cpp
│ │ └── http_page.h
│ ├── websocket_parser.c
│ ├── websocket_parser.h
│ ├── wsdef.c
│ └── wsdef.h
├── hv.h
├── hv.rc.in
├── misc/
│ ├── grpc_server.h
│ └── win32_getopt.h
├── mqtt/
│ ├── mqtt_client.c
│ ├── mqtt_client.h
│ ├── mqtt_protocol.c
│ └── mqtt_protocol.h
├── protocol/
│ ├── README.md
│ ├── dns.c
│ ├── dns.h
│ ├── ftp.c
│ ├── ftp.h
│ ├── icmp.c
│ ├── icmp.h
│ ├── smtp.c
│ └── smtp.h
├── scripts/
│ ├── check.sh
│ ├── cmake_cross_compile.sh
│ ├── consul.py
│ ├── consul_agent.sh
│ ├── coredump.sh
│ ├── create_repo.sh
│ ├── libhv.cmake
│ ├── shini.sh
│ ├── test-coverage.sh
│ ├── toolchain.sh
│ ├── unittest.sh
│ └── websocket_server.py
├── ssl/
│ ├── appletls.c
│ ├── gnutls.c
│ ├── hssl.c
│ ├── hssl.h
│ ├── mbedtls.c
│ ├── nossl.c
│ ├── openssl.c
│ └── wintls.c
├── unittest/
│ ├── CMakeLists.txt
│ ├── base64_test.c
│ ├── connect_test.c
│ ├── date_test.c
│ ├── defer_test.cpp
│ ├── ftp_test.c
│ ├── hatomic_test.c
│ ├── hatomic_test.cpp
│ ├── hbase_test.c
│ ├── hlog_test.c
│ ├── hmutex_test.c
│ ├── hpath_test.cpp
│ ├── hstring_test.cpp
│ ├── hthread_test.cpp
│ ├── hurl_test.cpp
│ ├── ifconfig_test.cpp
│ ├── listdir_test.cpp
│ ├── md5_test.c
│ ├── mkdir_test.c
│ ├── nslookup_test.c
│ ├── objectpool_test.cpp
│ ├── ping_test.c
│ ├── rbtree_test.c
│ ├── rmdir_test.c
│ ├── sendmail_test.c
│ ├── sha1_test.c
│ ├── sizeof_test.cpp
│ ├── socketpair_test.c
│ ├── synchronized_test.cpp
│ ├── threadpool_test.cpp
│ └── webbench.c
└── util/
├── README.md
├── base64.c
├── base64.h
├── md5.c
├── md5.h
├── sha1.c
└── sha1.h
Showing preview only (219K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (2614 symbols across 265 files)
FILE: base/hatomic.h
type atomic_bool (line 32) | typedef volatile bool atomic_bool;
type atomic_char (line 33) | typedef volatile char atomic_char;
type atomic_uchar (line 34) | typedef volatile unsigned char atomic_uchar;
type atomic_short (line 35) | typedef volatile short atomic_short;
type atomic_ushort (line 36) | typedef volatile unsigned short atomic_ushort;
type atomic_int (line 37) | typedef volatile int atomic_int;
type atomic_uint (line 38) | typedef volatile unsigned int atomic_uint;
type atomic_long (line 39) | typedef volatile long atomic_long;
type atomic_ulong (line 40) | typedef volatile unsigned long atomic_ulong;
type atomic_llong (line 41) | typedef volatile long long atomic_llong;
type atomic_ullong (line 42) | typedef volatile unsigned long long atomic_ullong;
type atomic_size_t (line 43) | typedef volatile size_t atomic_size_t;
type atomic_flag (line 45) | typedef struct atomic_flag { atomic_long _Value; } atomic_flag;
function atomic_flag_test_and_set (line 50) | static inline bool atomic_flag_test_and_set(atomic_flag* p) {
function atomic_flag_test_and_set (line 62) | static inline bool atomic_flag_test_and_set(atomic_flag* p) {
function atomic_flag_test_and_set (line 88) | static inline bool atomic_flag_test_and_set(atomic_flag* p) {
function atomic_flag_clear (line 97) | static inline void atomic_flag_clear(atomic_flag* p) {
type atomic_flag (line 118) | typedef atomic_flag hatomic_flag_t;
type atomic_long (line 123) | typedef atomic_long hatomic_t;
FILE: base/hbase.c
function hv_alloc_cnt (line 16) | long hv_alloc_cnt() {
function hv_free_cnt (line 20) | long hv_free_cnt() {
function hv_free (line 69) | void hv_free(void* ptr) {
function hv_strstartswith (line 139) | bool hv_strstartswith(const char* str, const char* start) {
function hv_strendswith (line 148) | bool hv_strendswith(const char* str, const char* end) {
function hv_strcontains (line 165) | bool hv_strcontains(const char* str, const char* sub) {
function hv_wildcard_match (line 170) | bool hv_wildcard_match(const char* str, const char* pattern) {
function hv_exists (line 286) | bool hv_exists(const char* path) {
function hv_isdir (line 290) | bool hv_isdir(const char* path) {
function hv_isfile (line 298) | bool hv_isfile(const char* path) {
function hv_islink (line 306) | bool hv_islink(const char* path) {
function hv_filesize (line 318) | size_t hv_filesize(const char* filepath) {
function hv_rand (line 363) | int hv_rand(int min, int max) {
function hv_getboolean (line 391) | bool hv_getboolean(const char* str) {
function hv_parse_size (line 405) | size_t hv_parse_size(const char* str) {
function time_t (line 428) | time_t hv_parse_time(const char* str) {
function hv_parse_url (line 452) | int hv_parse_url(hurl_t* stURL, const char* strURL) {
FILE: base/hbase.h
function HV_INLINE (line 53) | HV_INLINE void hv_memcheck(void) {
type hurl_field_e (line 121) | typedef enum {
type hurl_t (line 133) | typedef struct hurl_s {
FILE: base/hbuf.h
type hbuf_s (line 7) | struct hbuf_s {
type offset_buf_s (line 24) | struct offset_buf_s {
type fifo_buf_s (line 43) | struct fifo_buf_s {
function class (line 64) | class HBuf : public hbuf_t {
function virtual (line 74) | virtual ~HBuf() {
function size (line 79) | size_t size() { return len; }
function isNull (line 81) | bool isNull() { return base == NULL || len == 0; }
function cleanup (line 83) | void cleanup() {
function resize (line 91) | void resize(size_t cap) {
function copy (line 104) | void copy(void* data, size_t len) {
function copy (line 109) | void copy(hbuf_t* buf) {
function class (line 118) | class HVLBuf : public HBuf {
function HBuf (line 122) | HVLBuf(size_t cap) : HBuf(cap) {_offset = _size = 0;}
function virtual (line 123) | virtual ~HVLBuf() {}
function size (line 126) | size_t size() { return _size; }
function push_front (line 128) | void push_front(void* ptr, size_t len) {
function push_back (line 145) | void push_back(void* ptr, size_t len) {
function pop_front (line 159) | void pop_front(void* ptr, size_t len) {
function pop_back (line 170) | void pop_back(void* ptr, size_t len) {
function clear (line 179) | void clear() {
function prepend (line 183) | void prepend(void* ptr, size_t len) {
function append (line 187) | void append(void* ptr, size_t len) {
function insert (line 191) | void insert(void* ptr, size_t len) {
function remove (line 195) | void remove(size_t len) {
function class (line 204) | class HRingBuf : public HBuf {
FILE: base/heap.h
type heap_node (line 7) | struct heap_node {
type heap_node (line 13) | struct heap_node
type heap_node (line 13) | struct heap_node
type heap (line 14) | struct heap {
function heap_init (line 22) | static inline void heap_init(struct heap* heap, heap_compare_fn fn) {
function heap_replace (line 29) | static inline void heap_replace(struct heap* heap, struct heap_node* s, ...
function heap_swap (line 45) | static inline void heap_swap(struct heap* heap, struct heap_node* parent...
function heap_insert (line 76) | static inline void heap_insert(struct heap* heap, struct heap_node* node) {
function heap_remove (line 109) | static inline void heap_remove(struct heap* heap, struct heap_node* node) {
function heap_dequeue (line 168) | static inline void heap_dequeue(struct heap* heap) {
FILE: base/hendian.h
function htonll (line 46) | __inline unsigned __int64 htonll ( unsigned __int64 Value )
function ntohll (line 54) | __inline unsigned __int64 ntohll ( unsigned __int64 Value )
function htonf (line 62) | __inline unsigned __int32 htonf ( float Value )
function ntohf (line 73) | __inline float ntohf ( unsigned __int32 Value )
function htond (line 83) | __inline unsigned __int64 htond ( double Value )
function ntohd (line 94) | __inline double ntohd ( unsigned __int64 Value )
function detect_endian (line 197) | static inline int detect_endian() {
FILE: base/hlog.c
type logger_s (line 36) | struct logger_s {
function logger_init (line 59) | static void logger_init(logger_t* logger) {
function logger_t (line 81) | logger_t* logger_create() {
function logger_destroy (line 95) | void logger_destroy(logger_t* logger) {
function logger_set_handler (line 110) | void logger_set_handler(logger_t* logger, logger_handler fn) {
function logger_set_level (line 114) | void logger_set_level(logger_t* logger, int level) {
function logger_set_level_by_str (line 118) | void logger_set_level_by_str(logger_t* logger, const char* szLoglevel) {
function logger_set_format (line 140) | void logger_set_format(logger_t* logger, const char* format) {
function logger_set_remain_days (line 148) | void logger_set_remain_days(logger_t* logger, int days) {
function logger_set_truncate_percent (line 152) | void logger_set_truncate_percent(logger_t* logger, float percent) {
function logger_set_max_bufsize (line 157) | void logger_set_max_bufsize(logger_t* logger, unsigned int bufsize) {
function logger_enable_color (line 162) | void logger_enable_color(logger_t* logger, int on) {
function logger_set_file (line 166) | void logger_set_file(logger_t* logger, const char* filepath) {
function logger_set_max_filesize (line 175) | void logger_set_max_filesize(logger_t* logger, unsigned long long filesi...
function logger_set_max_filesize_by_str (line 179) | void logger_set_max_filesize_by_str(logger_t* logger, const char* str) {
function logger_enable_fsync (line 200) | void logger_enable_fsync(logger_t* logger, int on) {
function logger_fsync (line 204) | void logger_fsync(logger_t* logger) {
function logfile_name (line 216) | static void logfile_name(const char* filepath, time_t ts, char* buf, int...
function logfile_truncate (line 225) | static void logfile_truncate(logger_t* logger) {
function FILE (line 286) | static FILE* logfile_shift(logger_t* logger) {
function logfile_write (line 339) | static void logfile_write(logger_t* logger, const char* buf, int len) {
function i2a (line 349) | static int i2a(int i, char* buf, int len) {
function logger_print (line 361) | int logger_print(logger_t* logger, int level, const char* fmt, ...) {
function logger_t (line 502) | logger_t* hv_default_logger() {
function hv_destroy_default_logger (line 509) | void hv_destroy_default_logger(void) {
function stdout_logger (line 517) | void stdout_logger(int loglevel, const char* buf, int len) {
function stderr_logger (line 521) | void stderr_logger(int loglevel, const char* buf, int len) {
function file_logger (line 525) | void file_logger(int loglevel, const char* buf, int len) {
FILE: base/hlog.h
type log_level_e (line 56) | typedef enum {
type logger_t (line 82) | typedef struct logger_s logger_t;
FILE: base/hmain.c
function init_arg_kv (line 17) | static void init_arg_kv(int maxsize) {
function save_arg_kv (line 22) | static void save_arg_kv(const char* key, int key_len, const char* val, i...
function init_arg_list (line 34) | static void init_arg_list(int maxsize) {
function save_arg_list (line 39) | static void save_arg_list(const char* arg) {
function main_ctx_init (line 69) | int main_ctx_init(int argc, char** argv) {
function main_ctx_free (line 173) | void main_ctx_free(void) {
function get_arg_type (line 198) | static int get_arg_type(int short_opt, const char* options) {
function parse_opt (line 207) | int parse_opt(int argc, char** argv, const char* options) {
function option_t (line 243) | static const option_t* get_option(const char* opt, const option_t* long_...
function parse_opt_long (line 269) | int parse_opt_long(int argc, char** argv, const option_t* long_options, ...
function dump_opt_long (line 350) | int dump_opt_long(const option_t* long_options, int opt_size, char* out_...
function setproctitle (line 418) | void setproctitle(const char* fmt, ...) {
function create_pidfile (line 432) | int create_pidfile() {
function delete_pidfile (line 447) | void delete_pidfile(void) {
function pid_t (line 452) | pid_t getpid_from_pidfile() {
function signal_handler (line 468) | void signal_handler(int signo) {
function signal_init (line 537) | int signal_init(procedure_t reload_fn, void* reload_userdata) {
function on_timer (line 557) | static void WINAPI on_timer(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, ...
function signal_cleanup (line 579) | static void signal_cleanup(void) {
function signal_init (line 588) | int signal_init(procedure_t reload_fn, void* reload_userdata) {
function kill_proc (line 612) | static void kill_proc(int pid) {
function signal_handle (line 626) | void signal_handle(const char* signal) {
function signal_handle_noexit (line 630) | bool signal_handle_noexit(const char* signal) {
function HTHREAD_ROUTINE (line 679) | static HTHREAD_ROUTINE(worker_thread) {
function worker_init (line 687) | static void worker_init(void* userdata) {
function worker_proc (line 694) | static void worker_proc(void* userdata) {
function master_workers_run (line 701) | int master_workers_run(procedure_t worker_fn, void* worker_userdata,
FILE: base/hmain.h
type main_ctx_t (line 17) | typedef struct main_ctx_s {
type option_t (line 66) | typedef struct option_s {
FILE: base/hmath.h
function floor2e (line 6) | static inline unsigned long floor2e(unsigned long num) {
function ceil2e (line 15) | static inline unsigned long ceil2e(unsigned long num) {
function varint_encode (line 28) | static inline int varint_encode(long long value, unsigned char* buf) {
function varint_decode (line 42) | static inline long long varint_decode(const unsigned char* buf, int* len) {
function asn1_encode (line 68) | static inline int asn1_encode(long long value, unsigned char* buf) {
function asn1_decode (line 121) | static inline long long asn1_decode(const unsigned char* buf, int* len) {
FILE: base/hmutex.h
function BOOL (line 59) | static inline BOOL WINAPI s_once_func(INIT_ONCE* once, PVOID arg, PVOID*...
function honce (line 64) | static inline void honce(honce_t* once, honce_fn fn) {
function timespec_after (line 125) | static inline void timespec_after(struct timespec* ts, unsigned int ms) {
function htimed_mutex_lock_for (line 137) | static inline int htimed_mutex_lock_for(htimed_mutex_t* mutex, unsigned ...
function hcondvar_wait_for (line 163) | static inline int hcondvar_wait_for(hcondvar_t* cond, hmutex_t* mutex, u...
function hsem_wait_for (line 181) | static inline int hsem_wait_for(hsem_t* sem, unsigned int ms) {
function BEGIN_NAMESPACE_HV (line 213) | BEGIN_NAMESPACE_HV
function class (line 226) | class SpinLock {
function class (line 237) | class RWLock {
FILE: base/hplatform.h
type pid_t (line 230) | typedef int pid_t;
type gid_t (line 231) | typedef int gid_t;
type uid_t (line 232) | typedef int uid_t;
type BOOL (line 236) | typedef int BOOL;
type BYTE (line 237) | typedef unsigned char BYTE;
type WORD (line 238) | typedef unsigned short WORD;
type __int8 (line 313) | typedef __int8 int8_t;
type __int16 (line 314) | typedef __int16 int16_t;
type __int32 (line 315) | typedef __int32 int32_t;
type __int64 (line 316) | typedef __int64 int64_t;
type float32_t (line 323) | typedef float float32_t;
type float64_t (line 324) | typedef double float64_t;
FILE: base/hproc.h
type proc_ctx_t (line 6) | typedef struct proc_ctx_s {
function hproc_run (line 18) | static inline void hproc_run(proc_ctx_t* ctx) {
function hproc_spawn (line 32) | static inline int hproc_spawn(proc_ctx_t* ctx) {
function win_thread (line 52) | static void win_thread(void* userdata) {
function hproc_spawn (line 57) | static inline int hproc_spawn(proc_ctx_t* ctx) {
FILE: base/hsocket.c
function WSAInit (line 13) | void WSAInit() {
function WSADeinit (line 20) | void WSADeinit() {
function socket_errno_negative (line 28) | static inline int socket_errno_negative(int sockfd) {
function is_ipv4 (line 49) | bool is_ipv4(const char* host) {
function is_ipv6 (line 54) | bool is_ipv6(const char* host) {
function ResolveAddr (line 59) | int ResolveAddr(const char* host, sockaddr_u* addr) {
function sockaddr_port (line 99) | uint16_t sockaddr_port(sockaddr_u* addr) {
function sockaddr_set_ip (line 110) | int sockaddr_set_ip(sockaddr_u* addr, const char* host) {
function sockaddr_set_port (line 119) | void sockaddr_set_port(sockaddr_u* addr, int port) {
function sockaddr_set_ipport (line 128) | int sockaddr_set_ipport(sockaddr_u* addr, const char* host, int port) {
function socklen_t (line 142) | socklen_t sockaddr_len(sockaddr_u* addr) {
function else (line 171) | else if (addr->sa.sa_family == AF_UNIX) {
function sockaddr_compare (line 178) | int sockaddr_compare(const sockaddr_u* addr1, const sockaddr_u* addr2) {
function sockaddr_bind (line 198) | static int sockaddr_bind(sockaddr_u* localaddr, int type) {
function ListenFD (line 256) | static int ListenFD(int sockfd) {
function ConnectFDTimeout (line 265) | static int ConnectFDTimeout(int connfd, int ms) {
function Bind (line 306) | int Bind(int port, const char* host, int type) {
function Listen (line 319) | int Listen(int port, const char* host) {
function Connect (line 325) | int Connect(const char* host, int port, int nonblock) {
function ConnectNonblock (line 338) | int ConnectNonblock(const char* host, int port) {
function ConnectTimeout (line 342) | int ConnectTimeout(const char* host, int port, int ms) {
function BindUnix (line 356) | int BindUnix(const char* path, int type) {
function ListenUnix (line 363) | int ListenUnix(const char* path) {
function ConnectUnix (line 369) | int ConnectUnix(const char* path, int nonblock) {
function ConnectUnixNonblock (line 376) | int ConnectUnixNonblock(const char* path) {
function ConnectUnixTimeout (line 380) | int ConnectUnixTimeout(const char* path, int ms) {
function Socketpair (line 387) | int Socketpair(int family, int type, int protocol, int sv[2]) {
FILE: base/hsocket.h
function socket_errno (line 24) | int socket_errno() {
type SOCKET (line 35) | typedef SOCKET hsocket_t;
type socklen_t (line 36) | typedef int socklen_t;
function HV_INLINE (line 41) | HV_INLINE int blocking(int sockfd) {
function HV_INLINE (line 45) | HV_INLINE int nonblocking(int sockfd) {
type hsocket_t (line 67) | typedef int hsocket_t;
function HV_INLINE (line 77) | HV_INLINE int blocking(int s) {
function HV_INLINE (line 81) | HV_INLINE int nonblocking(int s) {
function HV_INLINE (line 86) | HV_INLINE int closesocket(int sockfd) {
type sockaddr_u (line 98) | typedef union {
function HV_INLINE (line 109) | HV_INLINE bool is_ipaddr(const char* host) {
function HV_INLINE (line 130) | HV_INLINE void sockaddr_set_path(sockaddr_u* addr, const char* path) {
function HV_INLINE (line 138) | HV_INLINE void sockaddr_print(sockaddr_u* addr) {
function HV_INLINE (line 178) | HV_INLINE int tcp_nodelay(int sockfd, int on DEFAULT(1)) {
function HV_INLINE (line 182) | HV_INLINE int tcp_nopush(int sockfd, int on DEFAULT(1)) {
function HV_INLINE (line 209) | HV_INLINE int udp_broadcast(int sockfd, int on DEFAULT(1)) {
function HV_INLINE (line 213) | HV_INLINE int ip_v6only(int sockfd, int on DEFAULT(1)) {
function HV_INLINE (line 222) | HV_INLINE int so_sndtimeo(int sockfd, int timeout) {
function HV_INLINE (line 232) | HV_INLINE int so_rcvtimeo(int sockfd, int timeout) {
function HV_INLINE (line 242) | HV_INLINE int so_sndbuf(int sockfd, int len) {
function HV_INLINE (line 247) | HV_INLINE int so_rcvbuf(int sockfd, int len) {
function HV_INLINE (line 251) | HV_INLINE int so_reuseaddr(int sockfd, int on DEFAULT(1)) {
function HV_INLINE (line 260) | HV_INLINE int so_reuseport(int sockfd, int on DEFAULT(1)) {
function HV_INLINE (line 269) | HV_INLINE int so_linger(int sockfd, int timeout DEFAULT(1)) {
FILE: base/hsysinfo.h
function get_ncpu (line 15) | static inline int get_ncpu() {
type meminfo_t (line 28) | typedef struct meminfo_s {
function get_meminfo (line 33) | static inline int get_meminfo(meminfo_t* mem) {
FILE: base/hthread.h
function hv_gettid (line 20) | static inline long hv_gettid() {
type HANDLE (line 54) | typedef HANDLE hthread_t;
function hthread_t (line 58) | static inline hthread_t hthread_create(hthread_routine fn, void* userdat...
function hthread_join (line 62) | static inline int hthread_join(hthread_t th) {
type pthread_t (line 70) | typedef pthread_t hthread_t;
function hthread_t (line 74) | static inline hthread_t hthread_create(hthread_routine fn, void* userdat...
function hthread_join (line 80) | static inline int hthread_join(hthread_t th) {
function class (line 98) | class HThread {
function virtual (line 134) | virtual int start() {
function virtual (line 147) | virtual int stop() {
function virtual (line 157) | virtual int pause() {
function virtual (line 164) | virtual int resume() {
function virtual (line 171) | virtual void run() {
function virtual (line 184) | virtual bool doPrepare() {return true;}
function virtual (line 185) | virtual void doTask() {}
function virtual (line 186) | virtual bool doFinish() {return true;}
FILE: base/htime.c
function gettick_ms (line 12) | unsigned int gettick_ms() {
function gethrtime_us (line 26) | unsigned long long gethrtime_us() {
function datetime_t (line 53) | datetime_t datetime_now() {
function datetime_t (line 75) | datetime_t datetime_localtime(time_t seconds) {
function time_t (line 87) | time_t datetime_mktime(datetime_t* dt) {
function days_of_month (line 102) | int days_of_month(int month, int year) {
function datetime_t (line 110) | datetime_t* datetime_past(datetime_t* dt, int days) {
function datetime_t (line 128) | datetime_t* datetime_future(datetime_t* dt, int days) {
type tm (line 174) | struct tm
function month_atoi (line 183) | int month_atoi(const char* month) {
function weekday_atoi (line 196) | int weekday_atoi(const char* weekday) {
function datetime_t (line 210) | datetime_t hv_compile_datetime() {
function time_t (line 219) | time_t cron_next_timeout(int minute, int hour, int day, int week, int mo...
FILE: base/htime.h
type datetime_t (line 16) | typedef struct datetime_s {
type timezone (line 35) | struct timezone {
function HV_INLINE (line 41) | HV_INLINE int gettimeofday(struct timeval *tv, struct timezone *tz) {
function gettimeofday_ms (line 57) | HV_INLINE unsigned long long gettimeofday_ms() {
function gettimeofday_us (line 62) | HV_INLINE unsigned long long gettimeofday_us() {
FILE: base/hversion.c
function version_atoi (line 13) | int version_atoi(const char* str) {
function version_itoa (line 30) | void version_itoa(int num, char* str) {
FILE: base/hversion.h
function HV_INLINE (line 20) | HV_INLINE const char* hv_version() {
FILE: base/list.h
type list_head (line 24) | struct list_head {
type hlist_head (line 29) | struct hlist_head {
type hlist_node (line 33) | struct hlist_node {
function list_init (line 43) | static inline void list_init(struct list_head *list)
function __list_add (line 55) | static inline void __list_add(struct list_head *n,
function list_add (line 73) | static inline void list_add(struct list_head *n, struct list_head *head)
function list_add_tail (line 87) | static inline void list_add_tail(struct list_head *n, struct list_head *...
function __list_del (line 99) | static inline void __list_del(struct list_head * prev, struct list_head ...
function __list_del_entry (line 111) | static inline void __list_del_entry(struct list_head *entry)
function list_del (line 116) | static inline void list_del(struct list_head *entry)
function list_replace (line 130) | static inline void list_replace(struct list_head *old,
function list_replace_init (line 139) | static inline void list_replace_init(struct list_head *old,
function list_del_init (line 150) | static inline void list_del_init(struct list_head *entry)
function list_move (line 161) | static inline void list_move(struct list_head *list, struct list_head *h...
function list_move_tail (line 172) | static inline void list_move_tail(struct list_head *list,
function list_is_last (line 184) | static inline int list_is_last(const struct list_head *list,
function list_empty (line 194) | static inline int list_empty(const struct list_head *head)
function list_empty_careful (line 212) | static inline int list_empty_careful(const struct list_head *head)
function list_rotate_left (line 222) | static inline void list_rotate_left(struct list_head *head)
function list_is_singular (line 236) | static inline int list_is_singular(const struct list_head *head)
function __list_cut_position (line 241) | static inline void __list_cut_position(struct list_head *list,
function list_cut_position (line 267) | static inline void list_cut_position(struct list_head *list,
function __list_splice (line 281) | static inline void __list_splice(const struct list_head *list,
function list_splice (line 300) | static inline void list_splice(const struct list_head *list,
function list_splice_tail (line 312) | static inline void list_splice_tail(struct list_head *list,
function list_splice_init (line 326) | static inline void list_splice_init(struct list_head *list,
function list_splice_tail_init (line 343) | static inline void list_splice_tail_init(struct list_head *list,
function hlist_init (line 583) | static inline void hlist_init(struct hlist_node *h)
function hlist_unhashed (line 589) | static inline int hlist_unhashed(const struct hlist_node *h)
function hlist_empty (line 594) | static inline int hlist_empty(const struct hlist_head *h)
function __hlist_del (line 599) | static inline void __hlist_del(struct hlist_node *n)
function hlist_del (line 608) | static inline void hlist_del(struct hlist_node *n)
function hlist_del_init (line 615) | static inline void hlist_del_init(struct hlist_node *n)
function hlist_add_head (line 623) | static inline void hlist_add_head(struct hlist_node *n, struct hlist_hea...
function hlist_add_before (line 634) | static inline void hlist_add_before(struct hlist_node *n,
function hlist_add_after (line 643) | static inline void hlist_add_after(struct hlist_node *n,
function hlist_add_fake (line 655) | static inline void hlist_add_fake(struct hlist_node *n)
function hlist_move_list (line 664) | static inline void hlist_move_list(struct hlist_head *old,
FILE: base/netinet.h
type iphdr_t (line 22) | typedef struct iphdr_s {
type udphdr_t (line 45) | typedef struct udphdr_s {
type tcphdr_t (line 53) | typedef struct tcphdr_s {
type icmphdr_t (line 106) | typedef struct icmphdr_s {
type icmp_t (line 123) | typedef struct icmp_s {
function checksum (line 183) | static inline uint16_t checksum(uint8_t* buf, int len) {
FILE: base/rbtree.c
function __rb_rotate_left (line 25) | static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
function __rb_rotate_right (line 45) | static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
function rb_insert_color (line 65) | void rb_insert_color(struct rb_node *node, struct rb_root *root)
function __rb_erase_color (line 130) | static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
function rb_erase (line 222) | void rb_erase(struct rb_node *node, struct rb_root *root)
type rb_node (line 299) | struct rb_node
type rb_root (line 299) | struct rb_root
type rb_node (line 301) | struct rb_node
type rb_node (line 305) | struct rb_node
type rb_node (line 311) | struct rb_node
type rb_root (line 311) | struct rb_root
type rb_node (line 313) | struct rb_node
type rb_node (line 317) | struct rb_node
type rb_node (line 323) | struct rb_node
type rb_node (line 323) | struct rb_node
type rb_node (line 346) | struct rb_node
type rb_node (line 346) | struct rb_node
function rb_replace_node (line 365) | void rb_replace_node(struct rb_node *victim, struct rb_node *newnode,
FILE: base/rbtree.h
type rb_node (line 99) | struct rb_node
type rb_root (line 109) | struct rb_root
type rb_node (line 123) | struct rb_node
type rb_root (line 123) | struct rb_root
type rb_node (line 124) | struct rb_node
type rb_root (line 124) | struct rb_root
type rb_node (line 127) | struct rb_node
type rb_node (line 127) | struct rb_node
type rb_node (line 128) | struct rb_node
type rb_node (line 128) | struct rb_node
type rb_node (line 129) | struct rb_node
type rb_root (line 129) | struct rb_root
type rb_node (line 130) | struct rb_node
type rb_root (line 130) | struct rb_root
type rb_node (line 133) | struct rb_node
type rb_node (line 133) | struct rb_node
type rb_root (line 134) | struct rb_root
function rb_link_node (line 140) | static inline void rb_link_node(struct rb_node *node, struct rb_node *pa...
FILE: cpputil/LRUCache.h
type Node (line 33) | struct Node {
function set_eviction_callback (line 71) | void set_eviction_callback(eviction_callback_t callback) {
function get (line 82) | bool get(const Key& key, Value& value) {
function Value (line 100) | Value* get(const Key& key) {
function put (line 118) | bool put(const Key& key, const Value& value) {
function remove (line 144) | bool remove(const Key& key) {
function contains (line 166) | bool contains(const Key& key) const {
FILE: cpputil/RAII.cpp
function LONG (line 9) | static LONG UnhandledException(EXCEPTION_POINTERS *pException) {
class WsaRAII (line 32) | class WsaRAII {
method WsaRAII (line 34) | WsaRAII() {
class CurlRAII (line 56) | class CurlRAII {
method CurlRAII (line 58) | CurlRAII() {
FILE: cpputil/ThreadLocalStorage.cpp
type hv (line 5) | namespace hv {
FILE: cpputil/ThreadLocalStorage.h
function namespace (line 28) | namespace hv {
FILE: cpputil/hasync.cpp
type hv (line 3) | namespace hv {
FILE: cpputil/hasync.h
function namespace (line 8) | namespace hv {
function class (line 29) | class async {
function cleanup (line 42) | static void cleanup() {
FILE: cpputil/hdir.cpp
function time_t (line 10) | time_t FileTime2Epoch(FILETIME filetime) {
function less (line 17) | static bool less(const hdir_t& lhs, const hdir_t& rhs) {
function listdir (line 21) | int listdir(const char* dir, std::list<hdir_t>& dirs) {
FILE: cpputil/hdir.h
type hdir_t (line 55) | typedef struct hdir_s {
FILE: cpputil/hfile.h
function class (line 9) | class HFile {
FILE: cpputil/hmap.h
function namespace (line 10) | namespace std {
function namespace (line 49) | namespace hv {
FILE: cpputil/hobjectpool.h
function ObjectNum (line 46) | int ObjectNum() { return _object_num; }
function IdleNum (line 47) | int IdleNum() { return objects_.size(); }
function BorrowNum (line 48) | int BorrowNum() { return ObjectNum() - IdleNum(); }
function Return (line 94) | void Return(std::shared_ptr<T>& pObj) {
function Add (line 101) | bool Add(std::shared_ptr<T>& pObj) {
function Remove (line 112) | bool Remove(std::shared_ptr<T>& pObj) {
function Clear (line 128) | void Clear() {
function pool_ (line 148) | pool_(pool)
function T (line 162) | T* get() {
function operator (line 166) | operator bool() {
function T (line 174) | T operator*() {
FILE: cpputil/hpath.cpp
type stat (line 11) | struct stat
type stat (line 19) | struct stat
type stat (line 30) | struct stat
FILE: cpputil/hpath.h
function class (line 8) | class HV_EXPORT HPath {
FILE: cpputil/hscope.h
type std (line 5) | typedef std::function<void()> Function;
function class (line 10) | class Defer {
function class (line 19) | class ScopeCleanup {
FILE: cpputil/hstring.cpp
type hv (line 8) | namespace hv {
function startswith (line 52) | bool startswith(const std::string& str, const std::string& start) {
function endswith (line 57) | bool endswith(const std::string& str, const std::string& end) {
function contains (line 62) | bool contains(const std::string& str, const std::string& sub) {
function vscprintf (line 67) | static inline int vscprintf(const char* fmt, va_list ap) {
function asprintf (line 71) | std::string asprintf(const char* fmt, ...) {
function StringList (line 89) | StringList split(const std::string& str, char delim) {
function splitKV (line 114) | hv::KeyValue splitKV(const std::string& str, char kv_kv, char k_v) {
function trim (line 149) | std::string trim(const std::string& str, const char* chars) {
function ltrim (line 157) | std::string ltrim(const std::string& str, const char* chars) {
function rtrim (line 163) | std::string rtrim(const std::string& str, const char* chars) {
function trim_pairs (line 168) | std::string trim_pairs(const std::string& str, const char* pairs) {
function replace (line 183) | std::string replace(const std::string& str, const std::string& find, c...
function replaceAll (line 192) | std::string replaceAll(const std::string& str, const std::string& find...
function wchar_to_string (line 229) | std::string wchar_to_string(const UINT codePage, const std::wstring &w...
function string_to_wchar (line 239) | std::wstring string_to_wchar(const UINT codePage, const std::string &s...
FILE: cpputil/hstring.h
function namespace (line 17) | namespace hv {
FILE: cpputil/hthreadpool.h
function class (line 25) | class HThreadPool {
function setMinThreadNum (line 44) | void setMinThreadNum(int min_threads) {
function setMaxThreadNum (line 47) | void setMaxThreadNum(int max_threads) {
function setMaxIdleTime (line 50) | void setMaxIdleTime(int ms) {
function currentThreadNum (line 53) | int currentThreadNum() {
function idleThreadNum (line 56) | int idleThreadNum() {
function taskNum (line 59) | size_t taskNum() {
function isStarted (line 63) | bool isStarted() {
function isStopped (line 66) | bool isStopped() {
function stop (line 81) | int stop() {
function addThread (line 185) | void addThread(std::thread* thread) {
function delThread (line 199) | void delThread(std::thread::id id) {
type Status (line 227) | enum Status {
type ThreadData (line 232) | struct ThreadData {
FILE: cpputil/hurl.cpp
function is_unambiguous (line 31) | static inline bool is_unambiguous(char c) {
function char_in_str (line 39) | static inline bool char_in_str(char c, const char* str) {
function hex2i (line 45) | static inline unsigned char hex2i(char hex) {
type hv (line 186) | namespace hv {
function escapeHTML (line 188) | std::string escapeHTML(const std::string& str) {
FILE: cpputil/hurl.h
function class (line 8) | class HV_EXPORT HUrl {
function namespace (line 31) | namespace hv {
FILE: cpputil/ifconfig.cpp
function ifconfig (line 14) | int ifconfig(std::vector<ifconfig_t>& ifcs) {
function ifconfig (line 96) | int ifconfig(std::vector<ifconfig_t>& ifcs) {
function ifconfig (line 170) | int ifconfig(std::vector<ifconfig_t>& ifcs) {
function ifconfig (line 224) | int ifconfig(std::vector<ifconfig_t>& ifcs) {
FILE: cpputil/ifconfig.h
type ifconfig_t (line 13) | typedef struct ifconfig_s {
FILE: cpputil/iniparser.cpp
class IniNode (line 23) | class IniNode {
type Type (line 25) | enum Type {
method Add (line 46) | void Add(IniNode* pNode) {
method Del (line 50) | void Del(IniNode* pNode) {
method IniNode (line 60) | IniNode* Get(const std::string& label, Type type = INI_NODE_TYPE_KEY_V...
class IniSection (line 70) | class IniSection : public IniNode {
method IniSection (line 72) | IniSection() : IniNode(), section(label) {
class IniKeyValue (line 78) | class IniKeyValue : public IniNode {
method IniKeyValue (line 80) | IniKeyValue() : IniNode(), key(label) {
class IniComment (line 86) | class IniComment : public IniNode {
method IniComment (line 88) | IniComment() : IniNode(), comment(label) {
function HV_EXPORT (line 360) | HV_EXPORT bool IniParser::Get(const std::string& key, const std::string&...
function HV_EXPORT (line 366) | HV_EXPORT int IniParser::Get(const std::string& key, const std::string& ...
function HV_EXPORT (line 372) | HV_EXPORT float IniParser::Get(const std::string& key, const std::string...
function HV_EXPORT (line 378) | HV_EXPORT void IniParser::Set(const std::string& key, const bool& value,...
function HV_EXPORT (line 383) | HV_EXPORT void IniParser::Set(const std::string& key, const int& value, ...
function HV_EXPORT (line 388) | HV_EXPORT void IniParser::Set(const std::string& key, const float& value...
FILE: cpputil/iniparser.h
function class (line 15) | class HV_EXPORT IniParser {
FILE: cpputil/json.hpp
function NLOHMANN_JSON_NAMESPACE_BEGIN (line 261) | NLOHMANN_JSON_NAMESPACE_BEGIN
function NLOHMANN_JSON_NAMESPACE_END (line 272) | NLOHMANN_JSON_NAMESPACE_END
function from_json (line 2602) | inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) ...
type would_call_std_ (line 2941) | struct would_call_std_
type value_t (line 2999) | enum class value_t : std::uint8_t
function NLOHMANN_JSON_NAMESPACE_END (line 3064) | NLOHMANN_JSON_NAMESPACE_END
function NLOHMANN_JSON_NAMESPACE_BEGIN (line 3157) | NLOHMANN_JSON_NAMESPACE_BEGIN
function NLOHMANN_JSON_NAMESPACE_BEGIN (line 3203) | NLOHMANN_JSON_NAMESPACE_BEGIN
function NLOHMANN_JSON_NAMESPACE_BEGIN (line 3394) | NLOHMANN_JSON_NAMESPACE_BEGIN
class json_pointer (line 3543) | class json_pointer
type ordered_map (line 3554) | struct ordered_map
function NLOHMANN_JSON_NAMESPACE_BEGIN (line 3565) | NLOHMANN_JSON_NAMESPACE_BEGIN
function NLOHMANN_JSON_NAMESPACE_BEGIN (line 4357) | NLOHMANN_JSON_NAMESPACE_BEGIN
function NLOHMANN_JSON_NAMESPACE_BEGIN (line 4500) | NLOHMANN_JSON_NAMESPACE_BEGIN
class parse_error (line 4626) | class parse_error : public exception
method parse_error (line 4639) | static parse_error create(int id_, const position_t& pos, const std::s...
method parse_error (line 4647) | static parse_error create(int id_, std::size_t byte_, const std::strin...
method parse_error (line 4667) | parse_error(int id_, std::size_t byte_, const char* what_arg)
method position_string (line 4670) | static std::string position_string(const position_t& pos)
class invalid_iterator (line 4679) | class invalid_iterator : public exception
method invalid_iterator (line 4683) | static invalid_iterator create(int id_, const std::string& what_arg, B...
method JSON_HEDLEY_NON_NULL (line 4690) | JSON_HEDLEY_NON_NULL(3)
class type_error (line 4697) | class type_error : public exception
method type_error (line 4701) | static type_error create(int id_, const std::string& what_arg, BasicJs...
method JSON_HEDLEY_NON_NULL (line 4708) | JSON_HEDLEY_NON_NULL(3)
class out_of_range (line 4714) | class out_of_range : public exception
method out_of_range (line 4718) | static out_of_range create(int id_, const std::string& what_arg, Basic...
method JSON_HEDLEY_NON_NULL (line 4725) | JSON_HEDLEY_NON_NULL(3)
class other_error (line 4731) | class other_error : public exception
method other_error (line 4735) | static other_error create(int id_, const std::string& what_arg, BasicJ...
method JSON_HEDLEY_NON_NULL (line 4742) | JSON_HEDLEY_NON_NULL(3)
function NLOHMANN_JSON_NAMESPACE_BEGIN (line 4771) | NLOHMANN_JSON_NAMESPACE_BEGIN
function NLOHMANN_JSON_NAMESPACE_BEGIN (line 4797) | NLOHMANN_JSON_NAMESPACE_BEGIN
function NLOHMANN_JSON_NAMESPACE_BEGIN (line 4805) | NLOHMANN_JSON_NAMESPACE_BEGIN
function NLOHMANN_JSON_NAMESPACE_BEGIN (line 4820) | NLOHMANN_JSON_NAMESPACE_BEGIN
function NLOHMANN_JSON_NAMESPACE_BEGIN (line 5431) | NLOHMANN_JSON_NAMESPACE_BEGIN
function NLOHMANN_JSON_NAMESPACE_END (line 5452) | NLOHMANN_JSON_NAMESPACE_END
function NLOHMANN_JSON_NAMESPACE_END (line 5632) | NLOHMANN_JSON_NAMESPACE_END
function NLOHMANN_JSON_NAMESPACE_BEGIN (line 5678) | NLOHMANN_JSON_NAMESPACE_BEGIN
type adl_serializer (line 6135) | struct adl_serializer
method from_json (line 6140) | static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
method from_json (line 6150) | static auto from_json(BasicJsonType && j) noexcept(
method to_json (line 6160) | static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
function set_subtype (line 6241) | void set_subtype(subtype_type subtype_) noexcept
function subtype_type (line 6249) | constexpr subtype_type subtype() const noexcept
function has_subtype (line 6256) | constexpr bool has_subtype() const noexcept
function clear_subtype (line 6263) | void clear_subtype() noexcept
function NLOHMANN_JSON_NAMESPACE_BEGIN (line 6302) | NLOHMANN_JSON_NAMESPACE_BEGIN
function NLOHMANN_JSON_NAMESPACE_BEGIN (line 6479) | NLOHMANN_JSON_NAMESPACE_BEGIN
function NLOHMANN_JSON_NAMESPACE_BEGIN (line 7048) | NLOHMANN_JSON_NAMESPACE_BEGIN
function reset (line 8345) | void reset() noexcept
function char_int_type (line 8363) | char_int_type get()
function unget (line 8400) | void unget()
function add (line 8427) | void add(char_int_type c)
function number_unsigned_t (line 8444) | constexpr number_unsigned_t get_number_unsigned() const noexcept
function number_float_t (line 8450) | constexpr number_float_t get_number_float() const noexcept
function string_t (line 8456) | string_t& get_string()
function position_t (line 8471) | constexpr position_t get_position() const noexcept
function get_token_string (line 8479) | std::string get_token_string() const
function JSON_HEDLEY_RETURNS_NON_NULL (line 8503) | JSON_HEDLEY_RETURNS_NON_NULL
function skip_bom (line 8517) | bool skip_bom()
function skip_whitespace (line 8531) | void skip_whitespace()
function token_type (line 8540) | token_type scan()
function NLOHMANN_JSON_NAMESPACE_END (line 8665) | NLOHMANN_JSON_NAMESPACE_END
type detail (line 8796) | namespace detail
function unknown_size (line 8798) | constexpr std::size_t unknown_size()
class json_sax_dom_parser (line 8817) | class json_sax_dom_parser
method json_sax_dom_parser (line 8832) | explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exce...
method json_sax_dom_parser (line 8837) | json_sax_dom_parser(const json_sax_dom_parser&) = delete;
method json_sax_dom_parser (line 8838) | json_sax_dom_parser(json_sax_dom_parser&&) = default;
method json_sax_dom_parser (line 8839) | json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
method json_sax_dom_parser (line 8840) | json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default;
method null (line 8843) | bool null()
method boolean (line 8849) | bool boolean(bool val)
method number_integer (line 8855) | bool number_integer(number_integer_t val)
method number_unsigned (line 8861) | bool number_unsigned(number_unsigned_t val)
method number_float (line 8867) | bool number_float(number_float_t val, const string_t& /*unused*/)
method string (line 8873) | bool string(string_t& val)
method binary (line 8879) | bool binary(binary_t& val)
method start_object (line 8885) | bool start_object(std::size_t len)
method key (line 8908) | bool key(string_t& val)
method end_object (line 8918) | bool end_object()
method start_array (line 8936) | bool start_array(std::size_t len)
method end_array (line 8957) | bool end_array()
method parse_error (line 8976) | bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
method is_errored (line 8988) | constexpr bool is_errored() const
method handle_diagnostic_positions_for_json_value (line 8996) | void handle_diagnostic_positions_for_json_value(BasicJsonType& v)
method JSON_HEDLEY_RETURNS_NON_NULL (line 9070) | JSON_HEDLEY_RETURNS_NON_NULL
class json_sax_dom_callback_parser (line 9123) | class json_sax_dom_callback_parser
method json_sax_dom_callback_parser (line 9135) | json_sax_dom_callback_parser(BasicJsonType& r,
method json_sax_dom_callback_parser (line 9145) | json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = ...
method json_sax_dom_callback_parser (line 9146) | json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default;
method json_sax_dom_callback_parser (line 9147) | json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_...
method json_sax_dom_callback_parser (line 9148) | json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser...
method null (line 9151) | bool null()
method boolean (line 9157) | bool boolean(bool val)
method number_integer (line 9163) | bool number_integer(number_integer_t val)
method number_unsigned (line 9169) | bool number_unsigned(number_unsigned_t val)
method number_float (line 9175) | bool number_float(number_float_t val, const string_t& /*unused*/)
method string (line 9181) | bool string(string_t& val)
method binary (line 9187) | bool binary(binary_t& val)
method start_object (line 9193) | bool start_object(std::size_t len)
method key (line 9225) | bool key(string_t& val)
method end_object (line 9242) | bool end_object()
method start_array (line 9292) | bool start_array(std::size_t len)
method end_array (line 9324) | bool end_array()
method parse_error (line 9371) | bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
method is_errored (line 9383) | constexpr bool is_errored() const
method handle_diagnostic_positions_for_json_value (line 9391) | void handle_diagnostic_positions_for_json_value(BasicJsonType& v)
method handle_value (line 9470) | std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool s...
class json_sax_acceptor (line 9560) | class json_sax_acceptor
method null (line 9569) | bool null()
method boolean (line 9574) | bool boolean(bool /*unused*/)
method number_integer (line 9579) | bool number_integer(number_integer_t /*unused*/)
method number_unsigned (line 9584) | bool number_unsigned(number_unsigned_t /*unused*/)
method number_float (line 9589) | bool number_float(number_float_t /*unused*/, const string_t& /*unuse...
method string (line 9594) | bool string(string_t& /*unused*/)
method binary (line 9599) | bool binary(binary_t& /*unused*/)
method start_object (line 9604) | bool start_object(std::size_t /*unused*/ = detail::unknown_size())
method key (line 9609) | bool key(string_t& /*unused*/)
method end_object (line 9614) | bool end_object()
method start_array (line 9619) | bool start_array(std::size_t /*unused*/ = detail::unknown_size())
method end_array (line 9624) | bool end_array()
method parse_error (line 9629) | bool parse_error(std::size_t /*unused*/, const std::string& /*unused...
function NLOHMANN_JSON_NAMESPACE_BEGIN (line 9664) | NLOHMANN_JSON_NAMESPACE_BEGIN
function NLOHMANN_JSON_NAMESPACE_END (line 9804) | NLOHMANN_JSON_NAMESPACE_END
function NLOHMANN_JSON_NAMESPACE_BEGIN (line 12885) | NLOHMANN_JSON_NAMESPACE_BEGIN
function NLOHMANN_JSON_NAMESPACE_BEGIN (line 13409) | NLOHMANN_JSON_NAMESPACE_BEGIN
function NLOHMANN_JSON_NAMESPACE_END (line 13525) | NLOHMANN_JSON_NAMESPACE_END
function NLOHMANN_JSON_NAMESPACE_BEGIN (line 13580) | NLOHMANN_JSON_NAMESPACE_BEGIN
function pointer (line 13882) | pointer operator->() const
function iter_impl (line 13924) | iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
function iter_impl (line 13935) | iter_impl& operator++()
function iter_impl (line 13975) | iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
function iter_impl (line 13986) | iter_impl& operator--()
function iter_impl (line 14143) | iter_impl& operator+=(difference_type i)
function iter_impl (line 14180) | iter_impl& operator-=(difference_type i)
function iter_impl (line 14189) | iter_impl operator+(difference_type i) const
function friend (line 14200) | friend iter_impl operator+(difference_type i, const iter_impl& it)
function iter_impl (line 14211) | iter_impl operator-(difference_type i) const
function difference_type (line 14222) | difference_type operator-(const iter_impl& other) const
function reference (line 14251) | reference operator[](difference_type n) const
function reference (line 14305) | reference value() const
function NLOHMANN_JSON_NAMESPACE_BEGIN (line 14340) | NLOHMANN_JSON_NAMESPACE_BEGIN
function NLOHMANN_JSON_NAMESPACE_BEGIN (line 14473) | NLOHMANN_JSON_NAMESPACE_BEGIN
function NLOHMANN_JSON_NAMESPACE_BEGIN (line 14534) | NLOHMANN_JSON_NAMESPACE_BEGIN
function NLOHMANN_BASIC_JSON_TPL_DECLARATION (line 14554) | NLOHMANN_BASIC_JSON_TPL_DECLARATION
function json_pointer (line 14566) | explicit json_pointer(const string_t& s = "")
function string_t (line 14572) | string_t to_string() const
function friend (line 14593) | friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr)
function json_pointer (line 14602) | json_pointer& operator/=(const json_pointer& ptr)
function json_pointer (line 14612) | json_pointer& operator/=(string_t token)
function json_pointer (line 14620) | json_pointer& operator/=(std::size_t array_idx)
function friend (line 14627) | friend json_pointer operator/(const json_pointer& lhs,
function friend (line 14635) | friend json_pointer operator/(const json_pointer& lhs, string_t token) /...
function friend (line 14642) | friend json_pointer operator/(const json_pointer& lhs, std::size_t array...
function json_pointer (line 14649) | json_pointer parent_pointer() const
function pop_back (line 14663) | void pop_back()
function string_t (line 14675) | const string_t& back() const
function push_back (line 14687) | void push_back(const string_t& token)
function push_back (line 14694) | void push_back(string_t&& token)
function empty (line 14701) | bool empty() const noexcept
function BasicJsonType (line 14778) | BasicJsonType& get_and_create(BasicJsonType& j) const
function BasicJsonType (line 14858) | BasicJsonType& get_unchecked(BasicJsonType* ptr) const
function BasicJsonType (line 14926) | BasicJsonType& get_checked(BasicJsonType* ptr) const
function BasicJsonType (line 14984) | const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
function BasicJsonType (line 15033) | const BasicJsonType& get_checked(const BasicJsonType* ptr) const
function contains (line 15082) | bool contains(const BasicJsonType* ptr) const
function split (line 15170) | static std::vector<string_t> split(const string_t& reference_string)
function BasicJsonType (line 15310) | static BasicJsonType
function convert (line 15339) | json_pointer<string_t> convert() const&
function convert (line 15346) | json_pointer<string_t> convert()&&
function NLOHMANN_JSON_NAMESPACE_BEGIN (line 15513) | NLOHMANN_JSON_NAMESPACE_BEGIN
function NLOHMANN_JSON_NAMESPACE_BEGIN (line 15640) | NLOHMANN_JSON_NAMESPACE_BEGIN
function NLOHMANN_JSON_NAMESPACE_END (line 15762) | NLOHMANN_JSON_NAMESPACE_END
function NLOHMANN_JSON_NAMESPACE_BEGIN (line 17641) | NLOHMANN_JSON_NAMESPACE_BEGIN
function NLOHMANN_JSON_NAMESPACE_END (line 18738) | NLOHMANN_JSON_NAMESPACE_END
function hex_bytes (line 19398) | static std::string hex_bytes(std::uint8_t byte)
function is_negative_number (line 19409) | bool is_negative_number(NumberType x)
function is_negative_number (line 19415) | bool is_negative_number(NumberType /*unused*/)
function dump_integer (line 19435) | void dump_integer(NumberType x)
function dump_float (line 19520) | void dump_float(number_float_t x)
function dump_float (line 19541) | void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_dou...
function dump_float (line 19549) | void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_do...
function decode (line 19621) | static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, co...
function number_unsigned_t (line 19661) | number_unsigned_t remove_sign(number_unsigned_t x)
function number_unsigned_t (line 19676) | number_unsigned_t remove_sign(number_integer_t x) noexcept
function ordered_map (line 19763) | ordered_map() noexcept(noexcept(Container())) : Container{} {}
function ordered_map (line 19764) | explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container...
function ordered_map (line 19766) | ordered_map(It first, It last, const Allocator& alloc = Allocator())
function ordered_map (line 19768) | ordered_map(std::initializer_list<value_type> init, const Allocator& all...
function emplace (line 19771) | std::pair<iterator, bool> emplace(const key_type& key, T&& t)
function emplace (line 19786) | std::pair<iterator, bool> emplace(KeyType && key, T && t)
function T (line 19799) | T& operator[](const key_type& key)
function T (line 19806) | T & operator[](KeyType && key)
function T (line 19811) | const T& operator[](const key_type& key) const
function T (line 19818) | const T & operator[](KeyType && key) const
function T (line 19823) | T& at(const key_type& key)
function T (line 19838) | T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
function T (line 19851) | const T& at(const key_type& key) const
function T (line 19866) | const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-s...
function size_type (line 19879) | size_type erase(const key_type& key)
function size_type (line 19900) | size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-...
function iterator (line 19919) | iterator erase(iterator pos)
function iterator (line 19924) | iterator erase(iterator first, iterator last)
function size_type (line 19977) | size_type count(const key_type& key) const
function size_type (line 19991) | size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missin...
function iterator (line 20003) | iterator find(const key_type& key)
function iterator (line 20017) | iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-fo...
function const_iterator (line 20029) | const_iterator find(const key_type& key) const
function insert (line 20041) | std::pair<iterator, bool> insert( value_type&& value )
function insert (line 20046) | std::pair<iterator, bool> insert( const value_type& value )
function insert (line 20064) | void insert(InputIt first, InputIt last)
function NLOHMANN_JSON_NAMESPACE_BEGIN (line 20091) | NLOHMANN_JSON_NAMESPACE_BEGIN
function set_parents (line 20720) | void set_parents()
function iterator (line 20757) | iterator set_parents(iterator it, typename iterator::difference_type cou...
function reference (line 20770) | reference set_parent(reference j, std::size_t old_capacity = detail::unk...
function basic_json (line 20832) | basic_json(const value_t v)
function basic_json (line 20840) | basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-excepti...
function basic_json (line 20852) | basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-...
function basic_json (line 20924) | basic_json(initializer_list_t init,
function JSON_HEDLEY_WARN_UNUSED_RESULT (line 20982) | JSON_HEDLEY_WARN_UNUSED_RESULT
function JSON_HEDLEY_WARN_UNUSED_RESULT (line 20993) | JSON_HEDLEY_WARN_UNUSED_RESULT
function JSON_HEDLEY_WARN_UNUSED_RESULT (line 21004) | JSON_HEDLEY_WARN_UNUSED_RESULT
function JSON_HEDLEY_WARN_UNUSED_RESULT (line 21015) | JSON_HEDLEY_WARN_UNUSED_RESULT
function JSON_HEDLEY_WARN_UNUSED_RESULT (line 21026) | JSON_HEDLEY_WARN_UNUSED_RESULT
function JSON_HEDLEY_WARN_UNUSED_RESULT (line 21034) | JSON_HEDLEY_WARN_UNUSED_RESULT
function basic_json (line 21042) | basic_json(size_type cnt, const basic_json& val):
function basic_json (line 21054) | basic_json(InputIT first, InputIT last) // NOLINT(performance-unnecessar...
function basic_json (line 21163) | basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
function basic_json (line 21167) | basic_json(const basic_json& other)
function basic_json (line 21240) | basic_json(basic_json&& other) noexcept
function basic_json (line 21266) | basic_json& operator=(basic_json other) noexcept (
function value_t (line 21335) | constexpr value_t type() const noexcept
function is_primitive (line 21342) | constexpr bool is_primitive() const noexcept
function is_structured (line 21349) | constexpr bool is_structured() const noexcept
function is_null (line 21356) | constexpr bool is_null() const noexcept
function is_boolean (line 21363) | constexpr bool is_boolean() const noexcept
function is_number (line 21370) | constexpr bool is_number() const noexcept
function is_number_integer (line 21377) | constexpr bool is_number_integer() const noexcept
function is_number_unsigned (line 21384) | constexpr bool is_number_unsigned() const noexcept
function is_number_float (line 21391) | constexpr bool is_number_float() const noexcept
function is_object (line 21398) | constexpr bool is_object() const noexcept
function is_array (line 21405) | constexpr bool is_array() const noexcept
function is_string (line 21412) | constexpr bool is_string() const noexcept
function is_binary (line 21419) | constexpr bool is_binary() const noexcept
function is_discarded (line 21426) | constexpr bool is_discarded() const noexcept
function object_t (line 21457) | object_t* get_impl_ptr(object_t* /*unused*/) noexcept
function object_t (line 21463) | constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const...
function array_t (line 21469) | array_t* get_impl_ptr(array_t* /*unused*/) noexcept
function array_t (line 21475) | constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const n...
function string_t (line 21481) | string_t* get_impl_ptr(string_t* /*unused*/) noexcept
function string_t (line 21487) | constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const...
function boolean_t (line 21493) | boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
function boolean_t (line 21499) | constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) con...
function number_integer_t (line 21505) | number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
function number_integer_t (line 21511) | constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /...
function number_unsigned_t (line 21517) | number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
function number_unsigned_t (line 21523) | constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t*...
function number_float_t (line 21529) | number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
function number_float_t (line 21535) | constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unu...
function binary_t (line 21541) | binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
function binary_t (line 21547) | constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const...
function ReferenceType (line 21564) | static ReferenceType get_ref_impl(ThisType& obj)
function get_ptr (line 21597) | constexpr auto get_ptr() const noexcept -> decltype(std::declval<const b...
function ValueType (line 21689) | ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(no...
function BasicJsonType (line 21714) | BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
function basic_json (line 21737) | basic_json get_impl(detail::priority_tag<3> /*unused*/) const
function get_impl (line 21750) | constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
function get (line 21826) | auto get() noexcept -> decltype(std::declval<basic_json_t&>().template g...
function ValueType (line 21839) | ValueType & get_to(ValueType& v) const noexcept(noexcept(
function ValueType (line 21852) | ValueType & get_to(ValueType& v) const
function Array (line 21863) | Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays...
function ReferenceType (line 21875) | ReferenceType get_ref()
function ReferenceType (line 21886) | ReferenceType get_ref() const
function binary_t (line 21945) | binary_t& get_binary()
function binary_t (line 21957) | const binary_t& get_binary() const
function reference (line 21979) | reference at(size_type idx)
function const_reference (line 22002) | const_reference at(size_type idx) const
function reference (line 22025) | reference at(const typename object_t::key_type& key)
function reference (line 22045) | reference at(KeyType && key)
function const_reference (line 22063) | const_reference at(const typename object_t::key_type& key) const
function const_reference (line 22083) | const_reference at(KeyType && key) const
function reference (line 22101) | reference operator[](size_type idx)
function const_reference (line 22147) | const_reference operator[](size_type idx) const
function reference (line 22160) | reference operator[](typename object_t::key_type key) // NOLINT(performa...
function const_reference (line 22182) | const_reference operator[](const typename object_t::key_type& key) const
function reference (line 22198) | reference operator[](T* key)
function const_reference (line 22204) | const_reference operator[](T* key) const
function reference (line 22213) | reference operator[](KeyType && key)
function const_reference (line 22237) | const_reference operator[](KeyType && key) const
class ValueType (line 22263) | class ValueType
function ReturnType (line 22292) | ReturnType value(const typename object_t::key_type& key, ValueType && de...
function ValueType (line 22318) | ValueType value(KeyType && key, const ValueType& default_value) const
function ReturnType (line 22345) | ReturnType value(KeyType && key, ValueType && default_value) const
function ValueType (line 22368) | ValueType value(const json_pointer& ptr, const ValueType& default_value)...
function ReturnType (line 22393) | ReturnType value(const json_pointer& ptr, ValueType && default_value) const
function ValueType (line 22417) | ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, cons...
function ReturnType (line 22428) | ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, Val...
function reference (line 22435) | reference front()
function const_reference (line 22442) | const_reference front() const
function reference (line 22449) | reference back()
function const_reference (line 22458) | const_reference back() const
function IteratorType (line 22470) | IteratorType erase(IteratorType pos) // NOLINT(performance-unnecessary-v...
function IteratorType (line 22540) | IteratorType erase(IteratorType first, IteratorType last) // NOLINT(perf...
function erase_internal (line 22608) | private:
function size_type (line 22624) | size_type erase_internal(KeyType && key)
function size_type (line 22656) | size_type erase(KeyType && key)
function erase (line 22663) | void erase(const size_type idx)
function iterator (line 22692) | iterator find(const typename object_t::key_type& key)
function const_iterator (line 22706) | const_iterator find(const typename object_t::key_type& key) const
function iterator (line 22722) | iterator find(KeyType && key)
function const_iterator (line 22738) | const_iterator find(KeyType && key) const
function size_type (line 22752) | size_type count(const typename object_t::key_type& key) const
function size_type (line 22762) | size_type count(KeyType && key) const
function contains (line 22770) | bool contains(const typename object_t::key_type& key) const
function contains (line 22779) | bool contains(KeyType && key) const
function contains (line 22786) | bool contains(const json_pointer& ptr) const
function contains (line 22793) | bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& pt...
function iterator (line 22809) | iterator begin() noexcept
function const_iterator (line 22818) | const_iterator begin() const noexcept
function const_iterator (line 22825) | const_iterator cbegin() const noexcept
function iterator (line 22834) | iterator end() noexcept
function const_iterator (line 22843) | const_iterator end() const noexcept
function const_iterator (line 22850) | const_iterator cend() const noexcept
function reverse_iterator (line 22859) | reverse_iterator rbegin() noexcept
function const_reverse_iterator (line 22866) | const_reverse_iterator rbegin() const noexcept
function reverse_iterator (line 22873) | reverse_iterator rend() noexcept
function const_reverse_iterator (line 22880) | const_reverse_iterator rend() const noexcept
function const_reverse_iterator (line 22887) | const_reverse_iterator crbegin() const noexcept
function const_reverse_iterator (line 22894) | const_reverse_iterator crend() const noexcept
function iterator_wrapper (line 22906) | static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
function iterator_wrapper (line 22917) | static iteration_proxy<const_iterator> iterator_wrapper(const_reference ...
function items (line 22924) | iteration_proxy<iterator> items() noexcept
function items (line 22931) | iteration_proxy<const_iterator> items() const noexcept
function empty (line 22947) | bool empty() const noexcept
function size_type (line 22986) | size_type size() const noexcept
function size_type (line 23025) | size_type max_size() const noexcept
function clear (line 23068) | void clear() noexcept
function push_back (line 23129) | void push_back(basic_json&& val)
function reference (line 23154) | reference operator+=(basic_json&& val)
function push_back (line 23162) | void push_back(const basic_json& val)
function reference (line 23186) | reference operator+=(const basic_json& val)
function push_back (line 23194) | void push_back(const typename object_t::value_type& val)
function reference (line 23217) | reference operator+=(const typename object_t::value_type& val)
function push_back (line 23225) | void push_back(initializer_list_t init)
function reference (line 23241) | reference operator+=(initializer_list_t init)
function reference (line 23250) | reference emplace_back(Args&& ... args)
function emplace (line 23275) | std::pair<iterator, bool> emplace(Args&& ... args)
function iterator (line 23307) | iterator insert_iterator(const_iterator pos, Args&& ... args) // NOLINT(...
function iterator (line 23326) | iterator insert(const_iterator pos, const basic_json& val) // NOLINT(per...
function iterator (line 23346) | iterator insert(const_iterator pos, basic_json&& val) // NOLINT(performa...
function iterator (line 23353) | iterator insert(const_iterator pos, size_type cnt, const basic_json& val...
function iterator (line 23373) | iterator insert(const_iterator pos, const_iterator first, const_iterator...
function iterator (line 23404) | iterator insert(const_iterator pos, initializer_list_t ilist) // NOLINT(...
function insert (line 23424) | void insert(const_iterator first, const_iterator last) // NOLINT(perform...
function update (line 23450) | void update(const_reference j, bool merge_objects = false)
function update (line 23457) | void update(const_iterator first, const_iterator last, bool merge_object...
function swap (line 23504) | void swap(reference other) noexcept (
function friend (line 23521) | friend void swap(reference left, reference right) noexcept (
function swap (line 23533) | void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoregui...
function swap (line 23549) | void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoregu...
function swap (line 23565) | void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoregu...
function swap (line 23581) | void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoregu...
function swap (line 23597) | void swap(typename binary_t::container_type& other) // NOLINT(bugprone-e...
function else (line 23686) | else if(compares_unordered(lhs, rhs))\
function compares_unordered (line 23715) | bool compares_unordered(const_reference rhs, bool inverse = false) const...
function friend (line 23828) | friend bool operator==(const_reference lhs, const_reference rhs) noexcept
function friend (line 23860) | friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
function friend (line 23917) | friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
function friend (line 23946) | friend bool operator>(const_reference lhs, const_reference rhs) noexcept
function friend (line 23976) | friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
function friend (line 24017) | friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
function JSON_HEDLEY_WARN_UNUSED_RESULT (line 24056) | JSON_HEDLEY_WARN_UNUSED_RESULT
function JSON_HEDLEY_WARN_UNUSED_RESULT (line 24070) | JSON_HEDLEY_WARN_UNUSED_RESULT
function basic_json (line 24084) | static basic_json parse(detail::span_input_adapter&& i,
function accept (line 24097) | static bool accept(InputType&& i,
function accept (line 24106) | static bool accept(IteratorType first, IteratorType last,
function accept (line 24114) | static bool accept(detail::span_input_adapter&& i,
function sax_parse (line 24124) | static bool sax_parse(InputType&& i, SAX* sax,
function sax_parse (line 24139) | static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
function sax_parse (line 24158) | static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
function JSON_HEDLEY_RETURNS_NON_NULL (line 24199) | JSON_HEDLEY_RETURNS_NON_NULL
type data (line 24231) | struct data
method data (line 24239) | data(const value_t v)
method data (line 24244) | data(size_type cnt, const basic_json& val)
method data (line 24250) | data() noexcept = default;
method data (line 24251) | data(data&&) noexcept = default;
method data (line 24252) | data(const data&) noexcept = delete;
method data (line 24253) | data& operator=(data&&) noexcept = delete;
method data (line 24254) | data& operator=(const data&) noexcept = delete;
function end_pos (line 24280) | constexpr std::size_t end_pos() const noexcept
function to_cbor (line 24305) | static void to_cbor(const basic_json& j, detail::output_adapter<std::uin...
function to_cbor (line 24312) | static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
function to_msgpack (line 24319) | static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
function to_msgpack (line 24328) | static void to_msgpack(const basic_json& j, detail::output_adapter<std::...
function to_msgpack (line 24335) | static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
function to_ubjson (line 24342) | static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
function to_ubjson (line 24353) | static void to_ubjson(const basic_json& j, detail::output_adapter<std::u...
function to_ubjson (line 24361) | static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
function to_bjdata (line 24369) | static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
function to_bjdata (line 24381) | static void to_bjdata(const basic_json& j, detail::output_adapter<std::u...
function to_bjdata (line 24390) | static void to_bjdata(const basic_json& j, detail::output_adapter<char> o,
function to_bson (line 24399) | static std::vector<std::uint8_t> to_bson(const basic_json& j)
function to_bson (line 24408) | static void to_bson(const basic_json& j, detail::output_adapter<std::uin...
function to_bson (line 24415) | static void to_bson(const basic_json& j, detail::output_adapter<char> o)
function JSON_HEDLEY_WARN_UNUSED_RESULT (line 24423) | JSON_HEDLEY_WARN_UNUSED_RESULT
function JSON_HEDLEY_WARN_UNUSED_RESULT (line 24439) | JSON_HEDLEY_WARN_UNUSED_RESULT
function basic_json (line 24455) | static basic_json from_cbor(const T* ptr, std::size_t len,
function basic_json (line 24465) | static basic_json from_cbor(detail::span_input_adapter&& i,
function JSON_HEDLEY_WARN_UNUSED_RESULT (line 24481) | JSON_HEDLEY_WARN_UNUSED_RESULT
function JSON_HEDLEY_WARN_UNUSED_RESULT (line 24496) | JSON_HEDLEY_WARN_UNUSED_RESULT
function basic_json (line 24511) | static basic_json from_msgpack(const T* ptr, std::size_t len,
function basic_json (line 24520) | static basic_json from_msgpack(detail::span_input_adapter&& i,
function JSON_HEDLEY_WARN_UNUSED_RESULT (line 24535) | JSON_HEDLEY_WARN_UNUSED_RESULT
function JSON_HEDLEY_WARN_UNUSED_RESULT (line 24550) | JSON_HEDLEY_WARN_UNUSED_RESULT
function basic_json (line 24565) | static basic_json from_ubjson(const T* ptr, std::size_t len,
function basic_json (line 24574) | static basic_json from_ubjson(detail::span_input_adapter&& i,
function JSON_HEDLEY_WARN_UNUSED_RESULT (line 24589) | JSON_HEDLEY_WARN_UNUSED_RESULT
function JSON_HEDLEY_WARN_UNUSED_RESULT (line 24604) | JSON_HEDLEY_WARN_UNUSED_RESULT
function JSON_HEDLEY_WARN_UNUSED_RESULT (line 24619) | JSON_HEDLEY_WARN_UNUSED_RESULT
function JSON_HEDLEY_WARN_UNUSED_RESULT (line 24634) | JSON_HEDLEY_WARN_UNUSED_RESULT
function basic_json (line 24649) | static basic_json from_bson(const T* ptr, std::size_t len,
function basic_json (line 24658) | static basic_json from_bson(detail::span_input_adapter&& i,
function reference (line 24680) | reference operator[](const json_pointer& ptr)
function reference (line 24687) | reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
function const_reference (line 24694) | const_reference operator[](const json_pointer& ptr) const
function const_reference (line 24701) | const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>...
function reference (line 24708) | reference at(const json_pointer& ptr)
function reference (line 24715) | reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
function const_reference (line 24722) | const_reference at(const json_pointer& ptr) const
function const_reference (line 24729) | const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) c...
function basic_json (line 24736) | basic_json flatten() const
function basic_json (line 24745) | basic_json unflatten() const
function patch_inplace (line 24761) | void patch_inplace(const basic_json& json_patch)
function basic_json (line 25032) | basic_json patch(const basic_json& json_patch) const
function JSON_HEDLEY_WARN_UNUSED_RESULT (line 25041) | JSON_HEDLEY_WARN_UNUSED_RESULT
function merge_patch (line 25184) | void merge_patch(const basic_json& apply_patch)
function NLOHMANN_BASIC_JSON_TPL_DECLARATION (line 25215) | NLOHMANN_BASIC_JSON_TPL_DECLARATION
function NLOHMANN_JSON_NAMESPACE_END (line 25252) | NLOHMANN_JSON_NAMESPACE_END
FILE: echo-servers/asio_echo.cpp
class session (line 17) | class session {
method session (line 19) | session(boost::asio::io_service& io_service) :
method start (line 27) | void start() {
method handle_read (line 34) | void handle_read(const boost::system::error_code& error,
method handle_write (line 45) | void handle_write(const boost::system::error_code& error) {
class server (line 64) | class server {
method server (line 66) | server(boost::asio::io_service& io_service, short port) :
method handle_accept (line 75) | void handle_accept(session* new_session,
function main (line 93) | int main(int argc, char** argv) {
FILE: echo-servers/libev_echo.c
function do_recv (line 15) | void do_recv(struct ev_loop *loop, struct ev_io *io, int revents) {
function do_accept (line 33) | void do_accept(struct ev_loop *loop, struct ev_io *listenio, int revents) {
function main (line 46) | int main(int argc, char** argv) {
FILE: echo-servers/libevent_echo.c
function error_cb (line 12) | void error_cb(struct bufferevent* bev, short event, void* userdata) {
function read_cb (line 16) | void read_cb(struct bufferevent* bev, void* userdata) {
function on_accept (line 28) | void on_accept(struct evconnlistener* listener, evutil_socket_t connfd, ...
function main (line 35) | int main(int argc, char** argv) {
FILE: echo-servers/libhv_echo.c
function on_close (line 3) | void on_close(hio_t* io) {
function on_recv (line 6) | void on_recv(hio_t* io, void* buf, int readbytes) {
function on_accept (line 10) | void on_accept(hio_t* io) {
function main (line 16) | int main(int argc, char** argv) {
FILE: echo-servers/libuv_echo.c
type uv_write_req_t (line 8) | typedef struct {
function alloc_cb (line 13) | void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
function close_cb (line 18) | void close_cb(uv_handle_t* handle) {
function write_cb (line 22) | void write_cb(uv_write_t* req, int status) {
function read_cb (line 28) | void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {
function do_accept (line 39) | void do_accept(uv_stream_t* server, int status) {
function main (line 46) | int main(int argc, char** argv) {
FILE: echo-servers/muduo_echo.cpp
class EchoTcpServer (line 19) | class EchoTcpServer {
method EchoTcpServer (line 21) | EchoTcpServer(EventLoop* loop, const InetAddress& addr)
method start (line 28) | void start() {
method onConnection (line 33) | void onConnection(const TcpConnectionPtr& conn) {
method onMessage (line 36) | void onMessage(const TcpConnectionPtr& conn,
function main (line 45) | int main(int argc, char** argv) {
FILE: echo-servers/pingpong_client.cpp
function print_help (line 36) | static void print_help() {
function print_cmd (line 41) | static void print_cmd() {
function print_result (line 46) | static void print_result() {
function on_close (line 53) | static void on_close(hio_t* io) {
function on_recv (line 61) | static void on_recv(hio_t* io, void* buf, int readbytes) {
function on_connect (line 67) | static void on_connect(hio_t* io) {
function start_connect (line 80) | static void start_connect(hloop_t* loop) {
function main (line 92) | int main(int argc, char** argv) {
FILE: echo-servers/poco_echo.cpp
class EchoServiceHandler (line 66) | class EchoServiceHandler
method EchoServiceHandler (line 69) | EchoServiceHandler(StreamSocket& socket, SocketReactor& reactor):
method onReadable (line 91) | void onReadable(const AutoPtr<ReadableNotification>& pNf)
method onShutdown (line 100) | void onShutdown(const AutoPtr<ShutdownNotification>& pNf)
class EchoServer (line 117) | class EchoServer: public Poco::Util::ServerApplication
method EchoServer (line 137) | EchoServer(): _helpRequested(false)
method initialize (line 146) | void initialize(Application& self)
method uninitialize (line 152) | void uninitialize()
method defineOptions (line 157) | void defineOptions(OptionSet& options)
method handleOption (line 167) | void handleOption(const std::string& name, const std::string& value)
method displayHelp (line 175) | void displayHelp()
method main (line 184) | int main(const std::vector<std::string>& args)
function main (line 221) | int main(int argc, char** argv)
FILE: event/epoll.c
type HANDLE (line 10) | typedef HANDLE epoll_handle_t;
type epoll_handle_t (line 13) | typedef int epoll_handle_t;
type epoll_event (line 19) | struct epoll_event
type epoll_ctx_t (line 21) | typedef struct epoll_ctx_s {
function iowatcher_init (line 26) | int iowatcher_init(hloop_t* loop) {
function iowatcher_cleanup (line 36) | int iowatcher_cleanup(hloop_t* loop) {
function iowatcher_add_event (line 45) | int iowatcher_add_event(hloop_t* loop, int fd, int events) {
function iowatcher_del_event (line 80) | int iowatcher_del_event(hloop_t* loop, int fd, int events) {
function iowatcher_poll_events (line 110) | int iowatcher_poll_events(hloop_t* loop, int timeout) {
FILE: event/evport.c
type evport_ctx_t (line 13) | typedef struct evport_ctx_s {
function evport_ctx_resize (line 20) | static void evport_ctx_resize(evport_ctx_t* evport_ctx, int size) {
function iowatcher_init (line 27) | int iowatcher_init(hloop_t* loop) {
function iowatcher_cleanup (line 40) | int iowatcher_cleanup(hloop_t* loop) {
function iowatcher_add_event (line 49) | int iowatcher_add_event(hloop_t* loop, int fd, int events) {
function iowatcher_del_event (line 79) | int iowatcher_del_event(hloop_t* loop, int fd, int events) {
function iowatcher_poll_events (line 106) | int iowatcher_poll_events(hloop_t* loop, int timeout) {
FILE: event/hevent.c
function hloop_next_event_id (line 9) | uint64_t hloop_next_event_id() {
function hio_next_id (line 14) | uint32_t hio_next_id() {
function fill_io_type (line 19) | static void fill_io_type(hio_t* io) {
function hio_socket_init (line 45) | static void hio_socket_init(hio_t* io) {
function hio_init (line 65) | void hio_init(hio_t* io) {
function hio_ready (line 82) | void hio_ready(hio_t* io) {
function hio_done (line 161) | void hio_done(hio_t* io) {
function hio_free (line 188) | void hio_free(hio_t* io) {
function hio_is_opened (line 198) | bool hio_is_opened(hio_t* io) {
function hio_is_connected (line 203) | bool hio_is_connected(hio_t* io) {
function hio_is_closed (line 208) | bool hio_is_closed(hio_t* io) {
function hio_id (line 213) | uint32_t hio_id (hio_t* io) {
function hio_fd (line 217) | int hio_fd(hio_t* io) {
function hio_type_e (line 221) | hio_type_e hio_type(hio_t* io) {
function hio_error (line 225) | int hio_error(hio_t* io) {
function hio_events (line 229) | int hio_events(hio_t* io) {
function hio_revents (line 233) | int hio_revents(hio_t* io) {
type sockaddr (line 237) | struct sockaddr
type sockaddr (line 241) | struct sockaddr
function hio_set_context (line 245) | void hio_set_context(hio_t* io, void* ctx) {
function haccept_cb (line 253) | haccept_cb hio_getcb_accept(hio_t* io) {
function hconnect_cb (line 257) | hconnect_cb hio_getcb_connect(hio_t* io) {
function hread_cb (line 261) | hread_cb hio_getcb_read(hio_t* io) {
function hwrite_cb (line 265) | hwrite_cb hio_getcb_write(hio_t* io) {
function hclose_cb (line 269) | hclose_cb hio_getcb_close(hio_t* io) {
function hio_setcb_accept (line 273) | void hio_setcb_accept(hio_t* io, haccept_cb accept_cb) {
function hio_setcb_connect (line 277) | void hio_setcb_connect(hio_t* io, hconnect_cb connect_cb) {
function hio_setcb_read (line 281) | void hio_setcb_read(hio_t* io, hread_cb read_cb) {
function hio_setcb_write (line 285) | void hio_setcb_write(hio_t* io, hwrite_cb write_cb) {
function hio_setcb_close (line 289) | void hio_setcb_close(hio_t* io, hclose_cb close_cb) {
function hio_accept_cb (line 293) | void hio_accept_cb(hio_t* io) {
function hio_connect_cb (line 308) | void hio_connect_cb(hio_t* io) {
function hio_handle_read (line 324) | void hio_handle_read(hio_t* io, void* buf, int readbytes) {
function hio_read_cb (line 392) | void hio_read_cb(hio_t* io, void* buf, int len) {
function hio_write_cb (line 415) | void hio_write_cb(hio_t* io, const void* buf, int len) {
function hio_close_cb (line 423) | void hio_close_cb(hio_t* io) {
function hio_set_type (line 434) | void hio_set_type(hio_t* io, hio_type_e type) {
function hio_set_localaddr (line 438) | void hio_set_localaddr(hio_t* io, struct sockaddr* addr, int addrlen) {
function hio_set_peeraddr (line 445) | void hio_set_peeraddr (hio_t* io, struct sockaddr* addr, int addrlen) {
function hio_enable_ssl (line 452) | int hio_enable_ssl(hio_t* io) {
function hio_is_ssl (line 457) | bool hio_is_ssl(hio_t* io) {
function hssl_t (line 461) | hssl_t hio_get_ssl(hio_t* io) {
function hssl_ctx_t (line 465) | hssl_ctx_t hio_get_ssl_ctx(hio_t* io) {
function hio_set_ssl (line 469) | int hio_set_ssl(hio_t* io, hssl_t ssl) {
function hio_set_ssl_ctx (line 475) | int hio_set_ssl_ctx(hio_t* io, hssl_ctx_t ssl_ctx) {
function hio_new_ssl_ctx (line 481) | int hio_new_ssl_ctx(hio_t* io, hssl_ctx_opt_t* opt) {
function hio_set_hostname (line 488) | int hio_set_hostname(hio_t* io, const char* hostname) {
function hio_del_connect_timer (line 498) | void hio_del_connect_timer(hio_t* io) {
function hio_del_close_timer (line 506) | void hio_del_close_timer(hio_t* io) {
function hio_del_read_timer (line 514) | void hio_del_read_timer(hio_t* io) {
function hio_del_write_timer (line 522) | void hio_del_write_timer(hio_t* io) {
function hio_del_keepalive_timer (line 530) | void hio_del_keepalive_timer(hio_t* io) {
function hio_del_heartbeat_timer (line 538) | void hio_del_heartbeat_timer(hio_t* io) {
function hio_set_connect_timeout (line 547) | void hio_set_connect_timeout(hio_t* io, int timeout_ms) {
function hio_set_close_timeout (line 551) | void hio_set_close_timeout(hio_t* io, int timeout_ms) {
function __read_timeout_cb (line 555) | static void __read_timeout_cb(htimer_t* timer) {
function hio_set_read_timeout (line 573) | void hio_set_read_timeout(hio_t* io, int timeout_ms) {
function __write_timeout_cb (line 591) | static void __write_timeout_cb(htimer_t* timer) {
function hio_set_write_timeout (line 609) | void hio_set_write_timeout(hio_t* io, int timeout_ms) {
function __keepalive_timeout_cb (line 627) | static void __keepalive_timeout_cb(htimer_t* timer) {
function hio_set_keepalive_timeout (line 646) | void hio_set_keepalive_timeout(hio_t* io, int timeout_ms) {
function __heartbeat_timer_cb (line 664) | static void __heartbeat_timer_cb(htimer_t* timer) {
function hio_set_heartbeat (line 671) | void hio_set_heartbeat(hio_t* io, int interval_ms, hio_send_heartbeat_fn...
function hio_alloc_readbuf (line 691) | void hio_alloc_readbuf(hio_t* io, int len) {
function hio_free_readbuf (line 708) | void hio_free_readbuf(hio_t* io) {
function hio_memmove_readbuf (line 718) | void hio_memmove_readbuf(hio_t* io) {
function hio_set_readbuf (line 733) | void hio_set_readbuf(hio_t* io, void* buf, size_t len) {
function hio_readbuf_t (line 742) | hio_readbuf_t* hio_get_readbuf(hio_t* io) {
function hio_set_max_read_bufsize (line 746) | void hio_set_max_read_bufsize (hio_t* io, uint32_t size) {
function hio_set_max_write_bufsize (line 750) | void hio_set_max_write_bufsize(hio_t* io, uint32_t size) {
function hio_write_bufsize (line 754) | size_t hio_write_bufsize(hio_t* io) {
function hio_read_once (line 758) | int hio_read_once (hio_t* io) {
function hio_read_until_length (line 763) | int hio_read_until_length(hio_t* io, unsigned int len) {
function hio_read_until_delim (line 788) | int hio_read_until_delim(hio_t* io, unsigned char delim) {
function hio_read_remain (line 816) | int hio_read_remain(hio_t* io) {
function hio_set_unpack (line 827) | void hio_set_unpack(hio_t* io, unpack_setting_t* setting) {
function hio_unset_unpack (line 863) | void hio_unset_unpack(hio_t* io) {
function hio_read_upstream (line 872) | void hio_read_upstream(hio_t* io) {
function hio_read_upstream_on_write_complete (line 880) | void hio_read_upstream_on_write_complete(hio_t* io, const void* buf, int...
function hio_write_upstream (line 888) | void hio_write_upstream(hio_t* io, void* buf, int bytes) {
function hio_close_upstream (line 900) | void hio_close_upstream(hio_t* io) {
function hio_setup_upstream (line 907) | void hio_setup_upstream(hio_t* io1, hio_t* io2) {
function hio_t (line 912) | hio_t* hio_get_upstream(hio_t* io) {
function hio_t (line 916) | hio_t* hio_setup_tcp_upstream(hio_t* io, const char* host, int port, int...
function hio_t (line 930) | hio_t* hio_setup_udp_upstream(hio_t* io, const char* host, int port) {
FILE: event/hevent.h
type hloop_s (line 31) | struct hloop_s {
type hidle_s (line 73) | struct hidle_s {
type htimer_s (line 86) | struct htimer_s {
function hio_is_loop_readbuf (line 235) | static inline bool hio_is_loop_readbuf(hio_t* io) {
function hio_is_alloced_readbuf (line 238) | static inline bool hio_is_alloced_readbuf(hio_t* io) {
FILE: event/hloop.c
function timers_compare (line 30) | static int timers_compare(const struct heap_node* lhs, const struct heap...
function hloop_process_idles (line 34) | static int hloop_process_idles(hloop_t* loop) {
function __hloop_process_timers (line 55) | static int __hloop_process_timers(struct heap* timers, uint64_t timeout) {
function hloop_process_timers (line 93) | static int hloop_process_timers(hloop_t* loop) {
function hloop_process_ios (line 100) | static int hloop_process_ios(hloop_t* loop, int timeout) {
function hloop_process_pendings (line 109) | static int hloop_process_pendings(hloop_t* loop) {
function hloop_process_events (line 140) | int hloop_process_events(hloop_t* loop, int timeout_ms) {
function hloop_stat_timer_cb (line 194) | static void hloop_stat_timer_cb(htimer_t* timer) {
function eventfd_read_cb (line 205) | static void eventfd_read_cb(hio_t* io, void* buf, int readbytes) {
function hloop_create_eventfds (line 236) | static int hloop_create_eventfds(hloop_t* loop) {
function hloop_destroy_eventfds (line 261) | static void hloop_destroy_eventfds(hloop_t* loop) {
function hloop_post_event (line 276) | void hloop_post_event(hloop_t* loop, hevent_t* ev) {
function hloop_init (line 314) | static void hloop_init(hloop_t* loop) {
function hloop_cleanup (line 356) | static void hloop_cleanup(hloop_t* loop) {
function hloop_t (line 426) | hloop_t* hloop_new(int flags) {
function hloop_free (line 435) | void hloop_free(hloop_t** pp) {
function hloop_run (line 447) | int hloop_run(hloop_t* loop) {
function hloop_wakeup (line 495) | int hloop_wakeup(hloop_t* loop) {
function hloop_stop (line 502) | int hloop_stop(hloop_t* loop) {
function hloop_pause (line 513) | int hloop_pause(hloop_t* loop) {
function hloop_resume (line 520) | int hloop_resume(hloop_t* loop) {
function hloop_status_e (line 527) | hloop_status_e hloop_status(hloop_t* loop) {
function hloop_update_time (line 531) | void hloop_update_time(hloop_t* loop) {
function hloop_now (line 539) | uint64_t hloop_now(hloop_t* loop) {
function hloop_now_ms (line 543) | uint64_t hloop_now_ms(hloop_t* loop) {
function hloop_now_us (line 547) | uint64_t hloop_now_us(hloop_t* loop) {
function hloop_now_hrtime (line 551) | uint64_t hloop_now_hrtime(hloop_t* loop) {
function hio_last_read_time (line 555) | uint64_t hio_last_read_time(hio_t* io) {
function hio_last_write_time (line 560) | uint64_t hio_last_write_time(hio_t* io) {
function hloop_pid (line 565) | long hloop_pid(hloop_t* loop) {
function hloop_tid (line 569) | long hloop_tid(hloop_t* loop) {
function hloop_count (line 573) | uint64_t hloop_count(hloop_t* loop) {
function hloop_nios (line 577) | uint32_t hloop_nios(hloop_t* loop) {
function hloop_ntimers (line 581) | uint32_t hloop_ntimers(hloop_t* loop) {
function hloop_nidles (line 585) | uint32_t hloop_nidles(hloop_t* loop) {
function hloop_nactives (line 589) | uint32_t hloop_nactives(hloop_t* loop) {
function hloop_set_userdata (line 593) | void hloop_set_userdata(hloop_t* loop, void* userdata) {
function signal_handler (line 602) | static void signal_handler(int signo) {
function hsignal_t (line 610) | hsignal_t* hsignal_add(hloop_t* loop, hsignal_cb cb, int signo) {
function hsignal_del (line 640) | void hsignal_del(hsignal_t* sig) {
function hidle_t (line 650) | hidle_t* hidle_add(hloop_t* loop, hidle_cb cb, uint32_t repeat) {
function __hidle_del (line 662) | static void __hidle_del(hidle_t* idle) {
function hidle_del (line 669) | void hidle_del(hidle_t* idle) {
function htimer_t (line 675) | htimer_t* htimer_add(hloop_t* loop, htimer_cb cb, uint32_t timeout_ms, u...
function htimer_reset (line 695) | void htimer_reset(htimer_t* timer, uint32_t timeout_ms) {
function htimer_t (line 721) | htimer_t* htimer_add_period(hloop_t* loop, htimer_cb cb,
function __htimer_del (line 744) | static void __htimer_del(htimer_t* timer) {
function htimer_del (line 755) | void htimer_del(htimer_t* timer) {
function hio_t (line 781) | static inline hio_t* __hio_get(hloop_t* loop, int fd) {
function hio_t (line 790) | hio_t* hio_get(hloop_t* loop, int fd) {
function hio_detach (line 808) | void hio_detach(hio_t* io) {
function hio_attach (line 815) | void hio_attach(hloop_t* loop, hio_t* io) {
function hio_exists (line 830) | bool hio_exists(hloop_t* loop, int fd) {
function hio_add (line 837) | int hio_add(hio_t* io, hio_cb cb, int events) {
function hio_del (line 864) | int hio_del(hio_t* io, int events) {
function hio_close_event_cb (line 885) | static void hio_close_event_cb(hevent_t* ev) {
function hio_close_async (line 892) | int hio_close_async(hio_t* io) {
function hio_t (line 903) | hio_t* hread(hloop_t* loop, int fd, void* buf, size_t len, hread_cb read...
function hio_t (line 917) | hio_t* hwrite(hloop_t* loop, int fd, const void* buf, size_t len, hwrite...
function hio_t (line 927) | hio_t* haccept(hloop_t* loop, int listenfd, haccept_cb accept_cb) {
function hio_t (line 937) | hio_t* hconnect (hloop_t* loop, int connfd, hconnect_cb connect_cb) {
function hclose (line 947) | void hclose (hloop_t* loop, int fd) {
function hio_t (line 953) | hio_t* hrecv (hloop_t* loop, int connfd, void* buf, size_t len, hread_cb...
function hio_t (line 963) | hio_t* hsend (hloop_t* loop, int connfd, const void* buf, size_t len, hw...
function hio_t (line 973) | hio_t* hrecvfrom (hloop_t* loop, int sockfd, void* buf, size_t len, hrea...
function hio_t (line 981) | hio_t* hsendto (hloop_t* loop, int sockfd, const void* buf, size_t len, ...
function hio_t (line 990) | hio_t* hio_create_socket(hloop_t* loop, const char* host, int port, hio_...
function hio_t (line 1045) | hio_t* hloop_create_tcp_server (hloop_t* loop, const char* host, int por...
function hio_t (line 1053) | hio_t* hloop_create_tcp_client (hloop_t* loop, const char* host, int por...
function hio_t (line 1062) | hio_t* hloop_create_ssl_server (hloop_t* loop, const char* host, int por...
function hio_t (line 1070) | hio_t* hloop_create_ssl_client (hloop_t* loop, const char* host, int por...
function hio_t (line 1079) | hio_t* hloop_create_udp_server(hloop_t* loop, const char* host, int port) {
function hio_t (line 1083) | hio_t* hloop_create_udp_client(hloop_t* loop, const char* host, int port) {
function hio_create_pipe (line 1087) | int hio_create_pipe(hloop_t* loop, hio_t* pipeio[2]) {
FILE: event/hloop.h
type hloop_t (line 9) | typedef struct hloop_s hloop_t;
type hevent_t (line 10) | typedef struct hevent_s hevent_t;
type hio_t (line 14) | typedef struct hio_s hio_t;
type hidle_t (line 15) | typedef struct hidle_s hidle_t;
type htimer_t (line 16) | typedef struct htimer_s htimer_t;
type htimeout_t (line 17) | typedef struct htimeout_s htimeout_t;
type hperiod_t (line 18) | typedef struct hperiod_s hperiod_t;
type hsignal_t (line 19) | typedef struct hevent_s hsignal_t;
type hloop_status_e (line 33) | typedef enum {
type hevent_type_e (line 40) | typedef enum {
type hevent_s (line 76) | struct hevent_s {
type hio_type_e (line 92) | typedef enum {
type hio_side_e (line 118) | typedef enum {
type hio_readbuf_t (line 291) | typedef struct fifo_buf_s hio_readbuf_t;
type sockaddr (line 381) | struct sockaddr
type sockaddr (line 409) | struct sockaddr
type sockaddr (line 410) | struct sockaddr
type unpack_mode_e (line 485) | typedef enum {
type unpack_coding_e (line 498) | typedef enum {
function HV_INLINE (line 629) | HV_INLINE void reconn_setting_init(reconn_setting_t* reconn) {
function HV_INLINE (line 639) | HV_INLINE void reconn_setting_reset(reconn_setting_t* reconn) {
function HV_INLINE (line 644) | HV_INLINE bool reconn_setting_can_retry(reconn_setting_t* reconn) {
function HV_INLINE (line 650) | HV_INLINE uint32_t reconn_setting_calc_delay(reconn_setting_t* reconn) {
type load_balance_e (line 667) | typedef enum {
type sockaddr (line 682) | struct sockaddr
function HV_INLINE (line 727) | HV_INLINE void kcp_setting_init_with_normal_mode(kcp_setting_t* setting) {
function HV_INLINE (line 735) | HV_INLINE void kcp_setting_init_with_fast_mode(kcp_setting_t* setting) {
function HV_INLINE (line 743) | HV_INLINE void kcp_setting_init_with_fast2_mode(kcp_setting_t* setting) {
function HV_INLINE (line 751) | HV_INLINE void kcp_setting_init_with_fast3_mode(kcp_setting_t* setting) {
FILE: event/io_uring.c
type io_uring_ctx_t (line 14) | typedef struct io_uring_ctx_s {
function iowatcher_init (line 19) | int iowatcher_init(hloop_t* loop) {
function iowatcher_cleanup (line 33) | int iowatcher_cleanup(hloop_t* loop) {
type io_uring_sqe (line 41) | struct io_uring_sqe
type io_uring (line 41) | struct io_uring
type io_uring_sqe (line 42) | struct io_uring_sqe
function iowatcher_add_event (line 51) | int iowatcher_add_event(hloop_t* loop, int fd, int events) {
function iowatcher_del_event (line 98) | int iowatcher_del_event(hloop_t* loop, int fd, int events) {
function iowatcher_poll_events (line 140) | int iowatcher_poll_events(hloop_t* loop, int timeout) {
FILE: event/iocp.c
type iocp_ctx_t (line 10) | typedef struct iocp_ctx_s {
function iowatcher_init (line 14) | int iowatcher_init(hloop_t* loop) {
function iowatcher_cleanup (line 23) | int iowatcher_cleanup(hloop_t* loop) {
function iowatcher_add_event (line 31) | int iowatcher_add_event(hloop_t* loop, int fd, int events) {
function iowatcher_del_event (line 43) | int iowatcher_del_event(hloop_t* loop, int fd, int events) {
function iowatcher_poll_events (line 51) | int iowatcher_poll_events(hloop_t* loop, int timeout) {
FILE: event/kcp/hkcp.c
function __kcp_output (line 11) | static int __kcp_output(const char* buf, int len, ikcpcb* ikcp, void* us...
function __kcp_update_timer_cb (line 20) | static void __kcp_update_timer_cb(htimer_t* timer) {
function kcp_release (line 26) | void kcp_release(kcp_t* kcp) {
function hio_set_kcp (line 39) | int hio_set_kcp(hio_t* io, kcp_setting_t* setting) {
function kcp_t (line 45) | kcp_t* hio_get_kcp(hio_t* io, uint32_t conv, struct sockaddr* addr) {
function hio_write_kcp_event_cb (line 83) | static void hio_write_kcp_event_cb(hevent_t* ev) {
function hio_write_kcp_async (line 92) | static int hio_write_kcp_async(hio_t* io, const void* data, size_t len, ...
function hio_write_kcp (line 109) | int hio_write_kcp(hio_t* io, const void* buf, size_t len, struct sockadd...
function hio_read_kcp (line 126) | int hio_read_kcp (hio_t* io, void* buf, int readbytes) {
FILE: event/kcp/hkcp.h
type kcp_t (line 14) | typedef struct kcp_s {
type sockaddr (line 24) | struct sockaddr
type sockaddr (line 26) | struct sockaddr
FILE: event/kcp/ikcp.c
function IUINT32 (line 123) | static inline IUINT32 _imin_(IUINT32 a, IUINT32 b) {
function IUINT32 (line 127) | static inline IUINT32 _imax_(IUINT32 a, IUINT32 b) {
function IUINT32 (line 131) | static inline IUINT32 _ibound_(IUINT32 lower, IUINT32 middle, IUINT32 up...
function _itimediff (line 136) | static inline long _itimediff(IUINT32 later, IUINT32 earlier)
type IKCPSEG (line 144) | typedef struct IKCPSEG IKCPSEG;
function ikcp_free (line 157) | static void ikcp_free(void *ptr) {
function ikcp_allocator (line 166) | void ikcp_allocator(void* (*new_malloc)(size_t), void (*new_free)(void*))
function IKCPSEG (line 173) | static IKCPSEG* ikcp_segment_new(ikcpcb *kcp, int size)
function ikcp_segment_delete (line 179) | static void ikcp_segment_delete(ikcpcb *kcp, IKCPSEG *seg)
function ikcp_log (line 185) | void ikcp_log(ikcpcb *kcp, int mask, const char *fmt, ...)
function ikcp_canlog (line 197) | static int ikcp_canlog(const ikcpcb *kcp, int mask)
function ikcp_output (line 204) | static int ikcp_output(ikcpcb *kcp, const void *data, int size)
function ikcp_qprint (line 216) | void ikcp_qprint(const char *name, const struct IQUEUEHEAD *head)
function ikcpcb (line 234) | ikcpcb* ikcp_create(IUINT32 conv, void *user)
function ikcp_release (line 301) | void ikcp_release(ikcpcb *kcp)
function ikcp_setoutput (line 348) | void ikcp_setoutput(ikcpcb *kcp, int (*output)(const char *buf, int len,
function ikcp_recv (line 358) | int ikcp_recv(ikcpcb *kcp, char *buffer, int len)
function ikcp_peeksize (line 441) | int ikcp_peeksize(const ikcpcb *kcp)
function ikcp_send (line 469) | int ikcp_send(ikcpcb *kcp, const char *buffer, int len)
function ikcp_update_ack (line 543) | static void ikcp_update_ack(ikcpcb *kcp, IINT32 rtt)
function ikcp_shrink_buf (line 560) | static void ikcp_shrink_buf(ikcpcb *kcp)
function ikcp_parse_ack (line 571) | static void ikcp_parse_ack(ikcpcb *kcp, IUINT32 sn)
function ikcp_parse_una (line 593) | static void ikcp_parse_una(ikcpcb *kcp, IUINT32 una)
function ikcp_parse_fastack (line 609) | static void ikcp_parse_fastack(ikcpcb *kcp, IUINT32 sn, IUINT32 ts)
function ikcp_ack_push (line 637) | static void ikcp_ack_push(ikcpcb *kcp, IUINT32 sn, IUINT32 ts)
function ikcp_ack_get (line 673) | static void ikcp_ack_get(const ikcpcb *kcp, int p, IUINT32 *sn, IUINT32 ...
function ikcp_parse_data (line 683) | void ikcp_parse_data(ikcpcb *kcp, IKCPSEG *newseg)
function ikcp_input (line 749) | int ikcp_input(ikcpcb *kcp, const char *data, long size)
function ikcp_wnd_unused (line 919) | static int ikcp_wnd_unused(const ikcpcb *kcp)
function ikcp_flush (line 931) | void ikcp_flush(ikcpcb *kcp)
function ikcp_update (line 1146) | void ikcp_update(ikcpcb *kcp, IUINT32 current)
function IUINT32 (line 1183) | IUINT32 ikcp_check(const ikcpcb *kcp, IUINT32 current)
function ikcp_setmtu (line 1223) | int ikcp_setmtu(ikcpcb *kcp, int mtu)
function ikcp_interval (line 1238) | int ikcp_interval(ikcpcb *kcp, int interval)
function ikcp_nodelay (line 1246) | int ikcp_nodelay(ikcpcb *kcp, int nodelay, int interval, int resend, int...
function ikcp_wndsize (line 1272) | int ikcp_wndsize(ikcpcb *kcp, int sndwnd, int rcvwnd)
function ikcp_waitsnd (line 1285) | int ikcp_waitsnd(const ikcpcb *kcp)
function IUINT32 (line 1292) | IUINT32 ikcp_getconv(const void *ptr)
FILE: event/kcp/ikcp.h
type ISTDUINT32 (line 28) | typedef unsigned int ISTDUINT32;
type ISTDINT32 (line 29) | typedef int ISTDINT32;
type ISTDUINT32 (line 32) | typedef unsigned long ISTDUINT32;
type ISTDINT32 (line 33) | typedef long ISTDINT32;
type UInt32 (line 35) | typedef UInt32 ISTDUINT32;
type SInt32 (line 36) | typedef SInt32 ISTDINT32;
type u_int32_t (line 39) | typedef u_int32_t ISTDUINT32;
type ISTDINT32 (line 40) | typedef int32_t ISTDINT32;
type u_int32_t (line 43) | typedef u_int32_t ISTDUINT32;
type ISTDINT32 (line 44) | typedef int32_t ISTDINT32;
type ISTDUINT32 (line 46) | typedef unsigned __int32 ISTDUINT32;
type __int32 (line 47) | typedef __int32 ISTDINT32;
type ISTDUINT32 (line 50) | typedef uint32_t ISTDUINT32;
type ISTDINT32 (line 51) | typedef int32_t ISTDINT32;
type ISTDUINT32 (line 53) | typedef unsigned long ISTDUINT32;
type ISTDINT32 (line 54) | typedef long ISTDINT32;
type IINT8 (line 64) | typedef char IINT8;
type IUINT8 (line 69) | typedef unsigned char IUINT8;
type IUINT16 (line 74) | typedef unsigned short IUINT16;
type IINT16 (line 79) | typedef short IINT16;
type ISTDINT32 (line 84) | typedef ISTDINT32 IINT32;
type ISTDUINT32 (line 89) | typedef ISTDUINT32 IUINT32;
type __int64 (line 95) | typedef __int64 IINT64;
type IINT64 (line 97) | typedef long long IINT64;
type IUINT64 (line 104) | typedef unsigned __int64 IUINT64;
type IUINT64 (line 106) | typedef unsigned long long IUINT64;
type IQUEUEHEAD (line 137) | struct IQUEUEHEAD {
type iqueue_head (line 141) | typedef struct IQUEUEHEAD iqueue_head;
type IKCPSEG (line 267) | struct IKCPSEG
type IKCPCB (line 289) | struct IKCPCB
type ikcpcb (line 320) | typedef struct IKCPCB ikcpcb;
FILE: event/kqueue.c
type kqueue_ctx_t (line 17) | typedef struct kqueue_ctx_s {
function kqueue_ctx_resize (line 26) | static void kqueue_ctx_resize(kqueue_ctx_t* kqueue_ctx, int size) {
function iowatcher_init (line 34) | int iowatcher_init(hloop_t* loop) {
function iowatcher_cleanup (line 48) | int iowatcher_cleanup(hloop_t* loop) {
function __add_event (line 58) | static int __add_event(hloop_t* loop, int fd, int event) {
function iowatcher_add_event (line 84) | int iowatcher_add_event(hloop_t* loop, int fd, int events) {
function __del_event (line 94) | static int __del_event(hloop_t* loop, int fd, int event) {
function iowatcher_del_event (line 123) | int iowatcher_del_event(hloop_t* loop, int fd, int events) {
function iowatcher_poll_events (line 133) | int iowatcher_poll_events(hloop_t* loop, int timeout) {
FILE: event/nio.c
function __connect_timeout_cb (line 10) | static void __connect_timeout_cb(htimer_t* timer) {
function __close_timeout_cb (line 23) | static void __close_timeout_cb(htimer_t* timer) {
function __accept_cb (line 36) | static void __accept_cb(hio_t* io) {
function __connect_cb (line 40) | static void __connect_cb(hio_t* io) {
function __read_cb (line 45) | static void __read_cb(hio_t* io, void* buf, int readbytes) {
function __write_cb (line 51) | static void __write_cb(hio_t* io, const void* buf, int writebytes) {
function __close_cb (line 57) | static void __close_cb(hio_t* io) {
function ssl_server_handshake (line 68) | static void ssl_server_handshake(hio_t* io) {
function ssl_client_handshake (line 89) | static void ssl_client_handshake(hio_t* io) {
function nio_accept (line 110) | static void nio_accept(hio_t* io) {
function nio_connect (line 177) | static void nio_connect(hio_t* io) {
function nio_connect_event_cb (line 230) | static void nio_connect_event_cb(hevent_t* ev) {
function nio_connect_async (line 237) | static int nio_connect_async(hio_t* io) {
function __nio_read (line 247) | static int __nio_read(hio_t* io, void* buf, int len) {
function __nio_write (line 272) | static int __nio_write(hio_t* io, const void* buf, int len, struct socka...
function nio_read (line 307) | static void nio_read(hio_t* io) {
function nio_write (line 358) | static void nio_write(hio_t* io) {
function hio_handle_events (line 418) | static void hio_handle_events(hio_t* io) {
function hio_accept (line 450) | int hio_accept(hio_t* io) {
function hio_read (line 479) | int hio_read (hio_t* io) {
function hio_write4 (line 493) | static int hio_write4 (hio_t* io, const void* buf, size_t len, struct so...
function hio_write (line 585) | int hio_write (hio_t* io, const void* buf, size_t len) {
function hio_sendto (line 589) | int hio_sendto (hio_t* io, const void* buf, size_t len, struct sockaddr*...
function hio_close (line 593) | int hio_close (hio_t* io) {
FILE: event/nlog.c
type network_logger_t (line 9) | typedef struct network_logger_s {
type nlog_client (line 15) | typedef struct nlog_client {
function on_close (line 23) | static void on_close(hio_t* io) {
function on_read (line 38) | static void on_read(hio_t* io, void* buf, int readbytes) {
function on_accept (line 44) | static void on_accept(hio_t* io) {
function network_logger (line 69) | void network_logger(int loglevel, const char* buf, int len) {
function hio_t (line 81) | hio_t* nlog_listen(hloop_t* loop, int port) {
FILE: event/noevent.c
function iowatcher_init (line 4) | int iowatcher_init(hloop_t* loop) {
function iowatcher_cleanup (line 8) | int iowatcher_cleanup(hloop_t* loop) {
function iowatcher_add_event (line 12) | int iowatcher_add_event(hloop_t* loop, int fd, int events) {
function iowatcher_del_event (line 16) | int iowatcher_del_event(hloop_t* loop, int fd, int events) {
function iowatcher_poll_events (line 20) | int iowatcher_poll_events(hloop_t* loop, int timeout) {
FILE: event/overlapio.c
function post_acceptex (line 10) | int post_acceptex(hio_t* listenio, hoverlapped_t* hovlp) {
function post_recv (line 43) | int post_recv(hio_t* io, hoverlapped_t* hovlp) {
function on_acceptex_complete (line 86) | static void on_acceptex_complete(hio_t* io) {
function on_connectex_complete (line 128) | static void on_connectex_complete(hio_t* io) {
function on_wsarecv_complete (line 156) | static void on_wsarecv_complete(hio_t* io) {
function on_wsasend_complete (line 190) | static void on_wsasend_complete(hio_t* io) {
function hio_handle_events (line 215) | static void hio_handle_events(hio_t* io) {
function hio_accept (line 243) | int hio_accept (hio_t* io) {
function hio_connect (line 251) | int hio_connect (hio_t* io) {
function hio_read (line 294) | int hio_read (hio_t* io) {
function hio_write4 (line 299) | static int hio_write4 (hio_t* io, const void* buf, size_t len, struct so...
function hio_write (line 382) | int hio_write (hio_t* io, const void* buf, size_t len) {
function hio_sendto (line 386) | int hio_sendto (hio_t* io, const void* buf, size_t len, struct sockaddr*...
function hio_close (line 390) | int hio_close (hio_t* io) {
FILE: event/overlapio.h
type hoverlapped_t (line 15) | typedef struct hoverlapped_s {
FILE: event/poll.c
type pollfd (line 18) | struct pollfd
type poll_ctx_t (line 20) | typedef struct poll_ctx_s {
function iowatcher_init (line 25) | int iowatcher_init(hloop_t* loop) {
function iowatcher_cleanup (line 34) | int iowatcher_cleanup(hloop_t* loop) {
function iowatcher_add_event (line 42) | int iowatcher_add_event(hloop_t* loop, int fd, int events) {
function iowatcher_del_event (line 74) | int iowatcher_del_event(hloop_t* loop, int fd, int events) {
function iowatcher_poll_events (line 101) | int iowatcher_poll_events(hloop_t* loop, int timeout) {
FILE: event/rudp.c
function rudp_entry_free (line 8) | void rudp_entry_free(rudp_entry_t* entry) {
function rudp_init (line 15) | void rudp_init(rudp_t* rudp) {
function rudp_cleanup (line 21) | void rudp_cleanup(rudp_t* rudp) {
function rudp_insert (line 33) | bool rudp_insert(rudp_t* rudp, rudp_entry_t* entry) {
function rudp_entry_t (line 60) | rudp_entry_t* rudp_search(rudp_t* rudp, struct sockaddr* addr) {
function rudp_entry_t (line 80) | rudp_entry_t* rudp_remove(rudp_t* rudp, struct sockaddr* addr) {
function rudp_entry_t (line 92) | rudp_entry_t* rudp_get(rudp_t* rudp, struct sockaddr* addr) {
function rudp_del (line 127) | void rudp_del(rudp_t* rudp, struct sockaddr* addr) {
function rudp_entry_t (line 139) | rudp_entry_t* hio_get_rudp(hio_t* io, struct sockaddr* addr) {
function hio_close_rudp_event_cb (line 145) | static void hio_close_rudp_event_cb(hevent_t* ev) {
function hio_close_rudp (line 151) | int hio_close_rudp(hio_t* io, struct sockaddr* peeraddr) {
FILE: event/rudp.h
type rudp_t (line 15) | typedef struct rudp_s {
type rudp_entry_t (line 20) | typedef struct rudp_entry_s {
type sockaddr (line 38) | struct sockaddr
type sockaddr (line 39) | struct sockaddr
type sockaddr (line 43) | struct sockaddr
type sockaddr (line 45) | struct sockaddr
type sockaddr (line 48) | struct sockaddr
FILE: event/select.c
type select_ctx_t (line 9) | typedef struct select_ctx_s {
function iowatcher_init (line 17) | int iowatcher_init(hloop_t* loop) {
function iowatcher_cleanup (line 30) | int iowatcher_cleanup(hloop_t* loop) {
function iowatcher_add_event (line 35) | int iowatcher_add_event(hloop_t* loop, int fd, int events) {
function iowatcher_del_event (line 58) | int iowatcher_del_event(hloop_t* loop, int fd, int events) {
function find_max_active_fd (line 79) | static int find_max_active_fd(hloop_t* loop) {
function remove_bad_fds (line 88) | static int remove_bad_fds(hloop_t* loop) {
type timeval (line 123) | struct timeval
FILE: event/unpack.c
function hio_unpack (line 7) | int hio_unpack(hio_t* io, void* buf, int readbytes) {
function hio_unpack_by_fixed_length (line 22) | int hio_unpack_by_fixed_length(hio_t* io, void* buf, int readbytes) {
function hio_unpack_by_delimiter (line 52) | int hio_unpack_by_delimiter(hio_t* io, void* buf, int readbytes) {
function hio_unpack_by_length_field (line 106) | int hio_unpack_by_length_field(hio_t* io, void* buf, int readbytes) {
FILE: event/wepoll/wepoll.c
type EPOLL_EVENTS (line 38) | enum EPOLL_EVENTS {
type SOCKET (line 71) | typedef uintptr_t SOCKET;
type epoll_data_t (line 73) | typedef union epoll_data {
type epoll_event (line 82) | struct epoll_event {
type epoll_event (line 99) | struct epoll_event
type epoll_event (line 102) | struct epoll_event
type LONG (line 143) | typedef LONG NTSTATUS;
type NTSTATUS (line 144) | typedef NTSTATUS* PNTSTATUS;
type IO_STATUS_BLOCK (line 166) | typedef struct _IO_STATUS_BLOCK {
type UNICODE_STRING (line 175) | typedef struct _UNICODE_STRING {
type OBJECT_ATTRIBUTES (line 184) | typedef struct _OBJECT_ATTRIBUTES {
type AFD_POLL_HANDLE_INFO (line 282) | typedef struct _AFD_POLL_HANDLE_INFO {
type AFD_POLL_INFO (line 288) | typedef struct _AFD_POLL_INFO {
function afd_create_device_handle (line 328) | int afd_create_device_handle(HANDLE iocp_handle,
function afd_poll (line 366) | int afd_poll(HANDLE afd_device_handle,
function afd_cancel_poll (line 394) | int afd_cancel_poll(HANDLE afd_device_handle,
type port_state_t (line 419) | typedef struct port_state port_state_t;
type queue_t (line 420) | typedef struct queue queue_t;
type sock_state_t (line 421) | typedef struct sock_state sock_state_t;
type ts_tree_node_t (line 422) | typedef struct ts_tree_node ts_tree_node_t;
type epoll_event (line 429) | struct epoll_event
type epoll_event (line 436) | struct epoll_event
type reflock_t (line 482) | typedef struct reflock {
type tree_t (line 499) | typedef struct tree tree_t;
type tree_node_t (line 500) | typedef struct tree_node tree_node_t;
type tree_t (line 502) | typedef struct tree {
type tree_node_t (line 506) | typedef struct tree_node {
type ts_tree_t (line 523) | typedef struct ts_tree {
type ts_tree_node_t (line 528) | typedef struct ts_tree_node {
function epoll_global_init (line 550) | int epoll_global_init(void) {
function HANDLE (line 555) | static HANDLE epoll__create(void) {
function HANDLE (line 577) | HANDLE epoll_create(int size) {
function HANDLE (line 584) | HANDLE epoll_create1(int flags) {
function epoll_close (line 591) | int epoll_close(HANDLE ephnd) {
function epoll_ctl (line 616) | int epoll_ctl(HANDLE ephnd, int op, SOCKET sock, struct epoll_event* ev) {
function epoll_wait (line 648) | int epoll_wait(HANDLE ephnd,
function errno_t (line 788) | static errno_t err__map_win_error_to_errno(DWORD error) {
function err_map_win_error (line 799) | void err_map_win_error(void) {
function err_set_win_error (line 803) | void err_set_win_error(DWORD error) {
function err_check_handle (line 808) | int err_check_handle(HANDLE handle) {
function BOOL (line 842) | static BOOL CALLBACK init__once_callback(INIT_ONCE* once,
function init (line 858) | int init(void) {
type FARPROC (line 879) | typedef FARPROC nt__fn_ptr_cast_t;
function nt_global_init (line 887) | int nt_global_init(void) {
type poll_group_t (line 908) | typedef struct poll_group poll_group_t;
type queue_node_t (line 910) | typedef struct queue_node queue_node_t;
type queue_node_t (line 922) | typedef struct queue_node {
type queue_t (line 927) | typedef struct queue {
type poll_group_t (line 948) | typedef struct poll_group {
function poll_group_t (line 955) | static poll_group_t* poll_group__new(port_state_t* port_state) {
function poll_group_delete (line 979) | void poll_group_delete(poll_group_t* poll_group) {
function poll_group_t (line 986) | poll_group_t* poll_group_from_queue_node(queue_node_t* queue_node) {
function HANDLE (line 990) | HANDLE poll_group_get_afd_device_handle(poll_group_t* poll_group) {
function poll_group_t (line 994) | poll_group_t* poll_group_acquire(port_state_t* port_state) {
function poll_group_release (line 1014) | void poll_group_release(poll_group_t* poll_group) {
type epoll_event (line 1035) | struct epoll_event
type epoll_event (line 1041) | struct epoll_event
type port_state_t (line 1053) | typedef struct port_state {
function port_state_t (line 1064) | static inline port_state_t* port__alloc(void) {
function port__free (line 1072) | static inline void port__free(port_state_t* port) {
function HANDLE (line 1077) | static inline HANDLE port__create_iocp(void) {
function port_state_t (line 1086) | port_state_t* port_new(HANDLE* iocp_handle_out) {
function port__close_iocp (line 1117) | static inline int port__close_iocp(port_state_t* port_state) {
function port_close (line 1127) | int port_close(port_state_t* port_state) {
function port_delete (line 1137) | int port_delete(port_state_t* port_state) {
function port__update_events (line 1168) | static int port__update_events(port_state_t* port_state) {
function port__update_events_if_polling (line 1186) | static inline void port__update_events_if_polling(port_state_t* port_sta...
function port__feed_events (line 1191) | static inline int port__feed_events(port_state_t* port_state,
function port__poll (line 1209) | static inline int port__poll(port_state_t* port_state,
function port_wait (line 1241) | int port_wait(port_state_t* port_state,
function port__ctl_add (line 1319) | static inline int port__ctl_add(port_state_t* port_state,
function port__ctl_mod (line 1336) | static inline int port__ctl_mod(port_state_t* port_state,
function port__ctl_del (line 1351) | static inline int port__ctl_del(port_state_t* port_state, SOCKET sock) {
function port__ctl_op (line 1361) | static inline int port__ctl_op(port_state_t* port_state,
function port_ctl (line 1377) | int port_ctl(port_state_t* port_state,
function port_register_socket (line 1390) | int port_register_socket(port_state_t* port_state,
function port_unregister_socket (line 1400) | void port_unregister_socket(port_state_t* port_state,
function sock_state_t (line 1405) | sock_state_t* port_find_socket(port_state_t* port_state, SOCKET socket) {
function port_request_socket_update (line 1412) | void port_request_socket_update(port_state_t* port_state,
function port_cancel_socket_update (line 1420) | void port_cancel_socket_update(port_state_t* port_state,
function port_add_deleted_socket (line 1428) | void port_add_deleted_socket(port_state_t* port_state,
function port_remove_deleted_socket (line 1436) | void port_remove_deleted_socket(port_state_t* port_state,
function HANDLE (line 1444) | HANDLE port_get_iocp_handle(port_state_t* port_state) {
function queue_t (line 1449) | queue_t* port_get_poll_group_queue(port_state_t* port_state) {
function port_state_t (line 1453) | port_state_t* port_state_from_handle_tree_node(ts_tree_node_t* tree_node) {
function ts_tree_node_t (line 1457) | ts_tree_node_t* port_state_to_handle_tree_node(port_state_t* port_state) {
function queue_init (line 1461) | void queue_init(queue_t* queue) {
function queue_node_init (line 1465) | void queue_node_init(queue_node_t* node) {
function queue__detach_node (line 1470) | static inline void queue__detach_node(queue_node_t* node) {
function queue_node_t (line 1475) | queue_node_t* queue_first(const queue_t* queue) {
function queue_node_t (line 1479) | queue_node_t* queue_last(const queue_t* queue) {
function queue_prepend (line 1483) | void queue_prepend(queue_t* queue, queue_node_t* node) {
function queue_append (line 1490) | void queue_append(queue_t* queue, queue_node_t* node) {
function queue_move_to_start (line 1497) | void queue_move_to_start(queue_t* queue, queue_node_t* node) {
function queue_move_to_end (line 1502) | void queue_move_to_end(queue_t* queue, queue_node_t* node) {
function queue_remove (line 1507) | void queue_remove(queue_node_t* node) {
function queue_is_empty (line 1512) | bool queue_is_empty(const queue_t* queue) {
function queue_is_enqueued (line 1516) | bool queue_is_enqueued(const queue_node_t* node) {
function reflock_global_init (line 1528) | int reflock_global_init(void) {
function reflock_init (line 1536) | void reflock_init(reflock_t* reflock) {
function reflock__signal_event (line 1540) | static void reflock__signal_event(void* address) {
function reflock__await_event (line 1547) | static void reflock__await_event(void* address) {
function reflock_ref (line 1554) | void reflock_ref(reflock_t* reflock) {
function reflock_unref (line 1562) | void reflock_unref(reflock_t* reflock) {
function reflock_unref_and_destroy (line 1572) | void reflock_unref_and_destroy(reflock_t* reflock) {
type sock__poll_status_t (line 1591) | typedef enum sock__poll_status {
type sock_state_t (line 1597) | typedef struct sock_state {
function sock_state_t (line 1611) | static inline sock_state_t* sock__alloc(void) {
function sock__free (line 1618) | static inline void sock__free(sock_state_t* sock_state) {
function sock__cancel_poll (line 1623) | static inline int sock__cancel_poll(sock_state_t* sock_state) {
function sock_state_t (line 1635) | sock_state_t* sock_new(port_state_t* port_state, SOCKET socket) {
function sock__delete (line 1676) | static int sock__delete(port_state_t* port_state,
function sock_delete (line 1705) | void sock_delete(port_state_t* port_state, sock_state_t* sock_state) {
function sock_force_delete (line 1709) | void sock_force_delete(port_state_t* port_state, sock_state_t* sock_stat...
function sock_set_event (line 1713) | int sock_set_event(port_state_t* port_state,
function DWORD (line 1730) | static inline DWORD sock__epoll_events_to_afd_events(uint32_t epoll_even...
function sock__afd_events_to_epoll_events (line 1751) | static inline uint32_t sock__afd_events_to_epoll_events(DWORD afd_events) {
function sock_update (line 1772) | int sock_update(port_state_t* port_state, sock_state_t* sock_state) {
function sock_feed_event (line 1834) | int sock_feed_event(port_state_t* port_state,
function sock_state_t (line 1889) | sock_state_t* sock_state_from_queue_node(queue_node_t* queue_node) {
function queue_node_t (line 1893) | queue_node_t* sock_state_to_queue_node(sock_state_t* sock_state) {
function sock_state_t (line 1897) | sock_state_t* sock_state_from_tree_node(tree_node_t* tree_node) {
function tree_node_t (line 1901) | tree_node_t* sock_state_to_tree_node(sock_state_t* sock_state) {
function ts_tree_init (line 1905) | void ts_tree_init(ts_tree_t* ts_tree) {
function ts_tree_node_init (line 1910) | void ts_tree_node_init(ts_tree_node_t* node) {
function ts_tree_add (line 1915) | int ts_tree_add(ts_tree_t* ts_tree, ts_tree_node_t* node, uintptr_t key) {
function ts_tree_node_t (line 1925) | static inline ts_tree_node_t* ts_tree__find_node(ts_tree_t* ts_tree,
function ts_tree_node_t (line 1934) | ts_tree_node_t* ts_tree_del_and_ref(ts_tree_t* ts_tree, uintptr_t key) {
function ts_tree_node_t (line 1950) | ts_tree_node_t* ts_tree_find_and_ref(ts_tree_t* ts_tree, uintptr_t key) {
function ts_tree_node_unref (line 1964) | void ts_tree_node_unref(ts_tree_node_t* node) {
function ts_tree_node_unref_and_destroy (line 1968) | void ts_tree_node_unref_and_destroy(ts_tree_node_t* node) {
function tree_init (line 1972) | void tree_init(tree_t* tree) {
function tree_node_init (line 1976) | void tree_node_init(tree_node_t* node) {
function tree__rotate_left (line 2001) | static inline void tree__rotate_left(tree_t* tree, tree_node_t* node) {
function tree__rotate_right (line 2005) | static inline void tree__rotate_right(tree_t* tree, tree_node_t* node) {
function tree_add (line 2036) | int tree_add(tree_t* tree, tree_node_t* node, uintptr_t key) {
function tree_del (line 2096) | void tree_del(tree_t* tree, tree_node_t* node) {
function tree_node_t (line 2169) | tree_node_t* tree_find(const tree_t* tree, uintptr_t key) {
function tree_node_t (line 2182) | tree_node_t* tree_root(const tree_t* tree) {
function ws_global_init (line 2194) | int ws_global_init(void) {
function SOCKET (line 2205) | static inline SOCKET ws__ioctl_get_bsp_socket(SOCKET socket, DWORD ioctl) {
function SOCKET (line 2223) | SOCKET ws_get_base_socket(SOCKET socket) {
FILE: event/wepoll/wepoll.h
type EPOLL_EVENTS (line 41) | enum EPOLL_EVENTS {
type SOCKET (line 74) | typedef uintptr_t SOCKET;
type epoll_data_t (line 76) | typedef union epoll_data {
type epoll_event (line 85) | struct epoll_event {
type epoll_event (line 102) | struct epoll_event
type epoll_event (line 105) | struct epoll_event
FILE: evpp/Buffer.h
function namespace (line 8) | namespace hv {
FILE: evpp/Channel.h
function namespace (line 14) | namespace hv {
function class (line 237) | class SocketChannel : public Channel {
function startConnect (line 326) | int startConnect(struct sockaddr* peeraddr) {
function startConnect (line 332) | int startConnect() {
function isConnected (line 339) | bool isConnected() {
type sockaddr (line 345) | struct sockaddr
type sockaddr (line 352) | struct sockaddr
function send_heartbeat (line 368) | static void send_heartbeat(hio_t* io) {
type std (line 376) | typedef std::shared_ptr<Channel> ChannelPtr;
type std (line 377) | typedef std::shared_ptr<SocketChannel> SocketChannelPtr;
FILE: evpp/Event.h
function namespace (line 9) | namespace hv {
FILE: evpp/EventLoop.h
function namespace (line 16) | namespace hv {
type std (line 239) | typedef std::shared_ptr<EventLoop> EventLoopPtr;
function EventLoop (line 242) | static inline EventLoop* tlsEventLoop() {
function TimerID (line 247) | static inline TimerID setTimer(int timeout_ms, TimerCallback cb, uint32_...
function killTimer (line 254) | static inline void killTimer(TimerID timerID) {
function resetTimer (line 261) | static inline void resetTimer(TimerID timerID, int timeout_ms) {
function TimerID (line 268) | static inline TimerID setTimeout(int timeout_ms, TimerCallback cb) {
function TimerID (line 272) | static inline TimerID setInterval(int interval_ms, TimerCallback cb) {
FILE: evpp/EventLoopThread.h
function namespace (line 10) | namespace hv {
function join (line 76) | void join() {
type std (line 112) | typedef std::shared_ptr<EventLoopThread> EventLoopThreadPtr;
FILE: evpp/EventLoopThreadPool.h
function namespace (line 7) | namespace hv {
FILE: evpp/EventLoopThreadPool_test.cpp
function onTimer (line 14) | static void onTimer(TimerID timerID, int n) {
function main (line 18) | int main(int argc, char* argv[]) {
FILE: evpp/EventLoopThread_test.cpp
function onTimer (line 14) | static void onTimer(TimerID timerID, int n) {
function main (line 18) | int main(int argc, char* argv[]) {
FILE: evpp/EventLoop_test.cpp
function onTimer (line 14) | static void onTimer(TimerID timerID, int n) {
function main (line 18) | int main(int argc, char* argv[]) {
FILE: evpp/Status.h
function namespace (line 6) | namespace hv {
FILE: evpp/TcpClient.h
function namespace (line 11) | namespace hv {
function createsocket (line 58) | int createsocket(struct sockaddr* remote_addr) {
function bind (line 83) | int bind(struct sockaddr* local_addr) {
function closesocket (line 95) | void closesocket() {
function startConnect (line 106) | int startConnect() {
function startReconnect (line 174) | int startReconnect() {
function start (line 187) | void start() {
function isConnected (line 191) | bool isConnected() {
function send (line 197) | int send(const void* data, int size) {
function send (line 201) | int send(Buffer* buf) {
function send (line 204) | int send(const std::string& str) {
function setConnectTimeout (line 220) | void setConnectTimeout(int ms) {
function setReconnect (line 224) | void setReconnect(reconn_setting_t* setting) {
function isReconnect (line 234) | bool isReconnect() {
function setUnpack (line 238) | void setUnpack(unpack_setting_t* setting) {
function EventLoopPtr (line 283) | const EventLoopPtr& loop() {
type TcpClientTmpl (line 311) | typedef TcpClientTmpl<SocketChannel> TcpClient;
FILE: evpp/TcpClientEventLoop_test.cpp
class MyTcpClient (line 20) | class MyTcpClient : public TcpClient {
method MyTcpClient (line 22) | MyTcpClient(EventLoopPtr loop = NULL) : TcpClient(loop) {
method connect (line 53) | int connect(int port) {
function TestMultiClientsRunInOneEventLoop (line 78) | int TestMultiClientsRunInOneEventLoop(int port, int nclients) {
function main (line 118) | int main(int argc, char* argv[]) {
FILE: evpp/TcpClient_test.cpp
function main (line 20) | int main(int argc, char* argv[]) {
FILE: evpp/TcpServer.h
function namespace (line 11) | namespace hv {
function closesocket (line 51) | void closesocket() {
function setMaxConnectionNum (line 63) | void setMaxConnectionNum(uint32_t num) {
function setLoadBalance (line 67) | void setLoadBalance(load_balance_e lb) {
function setThreadNum (line 72) | void setThreadNum(int num) {
function startAccept (line 76) | int startAccept() {
function stopAccept (line 103) | int stopAccept() {
function setUnpack (line 139) | void setUnpack(unpack_setting_t* setting) {
function TSocketChannelPtr (line 151) | const TSocketChannelPtr& addChannel(hio_t* io) {
function TSocketChannelPtr (line 159) | TSocketChannelPtr getChannelById(uint32_t id) {
function removeChannel (line 165) | void removeChannel(const TSocketChannelPtr& channel) {
function connectionNum (line 171) | size_t connectionNum() {
function foreachChannel (line 176) | int foreachChannel(std::function<void(const TSocketChannelPtr& channel)>...
function broadcast (line 191) | int broadcast(const std::string& str) {
function onAccept (line 245) | static void onAccept(hio_t* connio) {
type TcpServerTmpl (line 318) | typedef TcpServerTmpl<SocketChannel> TcpServer;
FILE: evpp/TcpServer_test.cpp
function main (line 18) | int main(int argc, char* argv[]) {
FILE: evpp/TimerThread.h
function namespace (line 6) | namespace hv {
FILE: evpp/TimerThread_test.cpp
type hv (line 11) | namespace hv {
class GlobalTimerThread (line 13) | class GlobalTimerThread : public TimerThread {
method GlobalTimerThread (line 16) | GlobalTimerThread() : TimerThread() {}
method TimerID (line 20) | static TimerID setTimeout(int timeout_ms, TimerCallback cb) {
method clearTimeout (line 24) | static void clearTimeout(TimerID timerID) {
method TimerID (line 28) | static TimerID setInterval(int interval_ms, TimerCallback cb) {
method clearInterval (line 32) | static void clearInterval(TimerID timerID) {
function main (line 41) | int main(int argc, char* argv[]) {
FILE: evpp/UdpClient.h
function namespace (line 9) | namespace hv {
function closesocket (line 68) | void closesocket() {
function startRecv (line 74) | int startRecv() {
function stopRecv (line 103) | int stopRecv() {
function start (line 109) | void start() {
type sockaddr (line 114) | struct sockaddr
type sockaddr (line 118) | struct sockaddr
type sockaddr (line 121) | struct sockaddr
function setKcp (line 126) | void setKcp(kcp_setting_t* setting) {
function EventLoopPtr (line 168) | const EventLoopPtr& loop() {
type UdpClientTmpl (line 193) | typedef UdpClientTmpl<SocketChannel> UdpClient;
FILE: evpp/UdpClient_test.cpp
function main (line 17) | int main(int argc, char* argv[]) {
FILE: evpp/UdpServer.h
function namespace (line 9) | namespace hv {
type sockaddr (line 94) | struct sockaddr
type sockaddr (line 97) | struct sockaddr
function setKcp (line 102) | void setKcp(kcp_setting_t* setting) {
function EventLoopPtr (line 142) | const EventLoopPtr& loop() {
type UdpServerTmpl (line 167) | typedef UdpServerTmpl<SocketChannel> UdpServer;
FILE: evpp/UdpServer_test.cpp
function main (line 16) | int main(int argc, char* argv[]) {
FILE: examples/consul/consul.cpp
function make_url (line 16) | static std::string make_url(const char* ip, int port, const char* url) {
function make_ServiceID (line 20) | static std::string make_ServiceID(consul_service_t* service) {
function register_service (line 51) | int register_service(consul_node_t* node, consul_service_t* service, con...
function deregister_service (line 84) | int deregister_service(consul_node_t* node, consul_service_t* service) {
function discover_services (line 101) | int discover_services(consul_node_t* node, const char* service_name, std...
FILE: examples/consul/main.cpp
function main (line 7) | int main(int argc, char* argv[]) {
FILE: examples/curl.cpp
type option (line 35) | struct option
function print_usage (line 90) | static void print_usage() {
function print_version (line 93) | static void print_version() {
function print_help (line 96) | static void print_help() {
function is_upper_string (line 102) | static bool is_upper_string(const char* str) {
function parse_data (line 108) | static int parse_data(char* arg, HttpRequest* req) {
function parse_cmdline (line 151) | static int parse_cmdline(int argc, char* argv[], HttpRequest* req) {
function main (line 247) | int main(int argc, char* argv[]) {
FILE: examples/hloop_test.c
function mylogger (line 14) | void mylogger(int loglevel, const char* buf, int len) {
function on_idle (line 26) | void on_idle(hidle_t* idle) {
function on_timer (line 31) | void on_timer(htimer_t* timer) {
function cron_minutely (line 38) | void cron_minutely(htimer_t* timer) {
function cron_hourly (line 43) | void cron_hourly(htimer_t* timer) {
function timer_write_log (line 48) | void timer_write_log(htimer_t* timer) {
function on_stdin (line 55) | void on_stdin(hio_t* io, void* buf, int readbytes) {
function on_custom_events (line 63) | void on_custom_events(hevent_t* ev) {
function on_signal (line 67) | void on_signal(hsignal_t* sig) {
function main (line 72) | int main() {
FILE: examples/hmain_test.cpp
type conf_ctx_s (line 18) | struct conf_ctx_s {
function conf_ctx_init (line 27) | inline void conf_ctx_init(conf_ctx_t* ctx) {
function print_version (line 52) | void print_version() {
function print_help (line 56) | void print_help() {
function parse_confile (line 62) | int parse_confile(const char* confile) {
function on_reload (line 150) | static void on_reload(void* userdata) {
function main (line 155) | int main(int argc, char** argv) {
function worker_fn (line 239) | void worker_fn(void* userdata) {
FILE: examples/htimer_test.c
function on_timer (line 4) | void on_timer(htimer_t* timer) {
function on_timer_add (line 9) | void on_timer_add(htimer_t* timer) {
function on_timer_del (line 15) | void on_timer_del(htimer_t* timer) {
function on_timer_reset (line 21) | void on_timer_reset(htimer_t* timer) {
function on_timer_quit (line 27) | void on_timer_quit(htimer_t* timer) {
function cron_hourly (line 33) | void cron_hourly(htimer_t* timer) {
function main (line 38) | int main() {
FILE: examples/http_client_test.cpp
function test_http_async_client (line 16) | static void test_http_async_client(HttpClient* cli, int* resp_cnt) {
function test_http_sync_client (line 36) | static void test_http_sync_client(HttpClient* cli) {
function test_requests (line 53) | static void test_requests() {
function test_axios (line 120) | static void test_axios() {
function main (line 163) | int main(int argc, char* argv[]) {
FILE: examples/http_server_test.cpp
function main (line 28) | int main(int argc, char** argv) {
FILE: examples/httpd/handler.h
function class (line 6) | class Handler {
FILE: examples/httpd/httpd.cpp
function print_version (line 30) | void print_version() {
function print_help (line 34) | void print_help() {
function parse_confile (line 40) | int parse_confile(const char* confile) {
function on_reload (line 259) | static void on_reload(void* userdata) {
function main (line 264) | int main(int argc, char** argv) {
FILE: examples/httpd/router.h
function class (line 6) | class Router {
FILE: examples/jsonrpc/cJSON.c
type error (line 88) | typedef struct {
function cJSON_GetErrorPtr (line 94) | CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
function cJSON_GetStringValue (line 99) | CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
function cJSON_GetNumberValue (line 109) | CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
function cJSON_Version (line 124) | CJSON_PUBLIC(const char*) cJSON_Version(void)
function case_insensitive_strcmp (line 133) | static int case_insensitive_strcmp(const unsigned char *string1, const u...
type internal_hooks (line 156) | typedef struct internal_hooks
function internal_free (line 169) | static void CJSON_CDECL internal_free(void *pointer)
function cJSON_InitHooks (line 209) | CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
function cJSON (line 241) | static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
function cJSON_Delete (line 253) | CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
function get_decimal_point (line 277) | static unsigned char get_decimal_point(void)
type parse_buffer (line 287) | typedef struct
function cJSON_bool (line 305) | static cJSON_bool parse_number(cJSON * const item, parse_buffer * const ...
function cJSON_SetNumberHelper (line 382) | CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
function cJSON_SetValuestring (line 400) | CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valu...
type printbuffer (line 427) | typedef struct
function update_offset (line 525) | static void update_offset(printbuffer * const buffer)
function cJSON_bool (line 538) | static cJSON_bool compare_double(double a, double b)
function cJSON_bool (line 545) | static cJSON_bool print_number(const cJSON * const item, printbuffer * c...
function parse_hex4 (line 611) | static unsigned parse_hex4(const unsigned char * const input)
function utf16_literal_to_utf8 (line 648) | static unsigned char utf16_literal_to_utf8(const unsigned char * const i...
function cJSON_bool (line 769) | static cJSON_bool parse_string(cJSON * const item, parse_buffer * const ...
function cJSON_bool (line 898) | static cJSON_bool print_string_ptr(const unsigned char * const input, pr...
function cJSON_bool (line 1020) | static cJSON_bool print_string(const cJSON * const item, printbuffer * c...
function parse_buffer (line 1034) | static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
function parse_buffer (line 1060) | static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)
function cJSON_ParseWithOpts (line 1075) | CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char ...
function cJSON_ParseWithLengthOpts (line 1091) | CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_...
function cJSON_Parse (line 1171) | CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
function cJSON_ParseWithLength (line 1176) | CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t bu...
function cJSON_Print (line 1248) | CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
function cJSON_PrintUnformatted (line 1253) | CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
function cJSON_PrintBuffered (line 1258) | CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffe...
function cJSON_PrintPreallocated (line 1288) | CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buff...
function cJSON_bool (line 1308) | static cJSON_bool parse_value(cJSON * const item, parse_buffer * const i...
function cJSON_bool (line 1363) | static cJSON_bool print_value(const cJSON * const item, printbuffer * co...
function cJSON_bool (line 1437) | static cJSON_bool parse_array(cJSON * const item, parse_buffer * const i...
function cJSON_bool (line 1535) | static cJSON_bool print_array(const cJSON * const item, printbuffer * co...
function cJSON_bool (line 1597) | static cJSON_bool parse_object(cJSON * const item, parse_buffer * const ...
function cJSON_bool (line 1710) | static cJSON_bool print_object(const cJSON * const item, printbuffer * c...
function cJSON_GetArraySize (line 1824) | CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
function cJSON (line 1847) | static cJSON* get_array_item(const cJSON *array, size_t index)
function cJSON_GetArrayItem (line 1866) | CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
function cJSON (line 1876) | static cJSON *get_object_item(const cJSON * const object, const char * c...
function cJSON_GetObjectItem (line 1908) | CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, co...
function cJSON_GetObjectItemCaseSensitive (line 1913) | CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * con...
function cJSON_HasObjectItem (line 1918) | CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const ...
function suffix_object (line 1924) | static void suffix_object(cJSON *prev, cJSON *item)
function cJSON (line 1931) | static cJSON *create_reference(const cJSON *item, const internal_hooks *...
function cJSON_bool (line 1952) | static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
function cJSON_AddItemToArray (line 1986) | CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item)
function cJSON_bool (line 2007) | static cJSON_bool add_item_to_object(cJSON * const object, const char * ...
function cJSON_AddItemToObject (line 2044) | CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char...
function cJSON_AddItemToObjectCS (line 2050) | CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const ch...
function cJSON_AddItemReferenceToArray (line 2055) | CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJS...
function cJSON_AddItemReferenceToObject (line 2065) | CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, c...
function cJSON_AddNullToObject (line 2075) | CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const c...
function cJSON_AddTrueToObject (line 2087) | CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const c...
function cJSON_AddFalseToObject (line 2099) | CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const ...
function cJSON_AddBoolToObject (line 2111) | CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const c...
function cJSON_AddNumberToObject (line 2123) | CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const...
function cJSON_AddStringToObject (line 2135) | CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const...
function cJSON_AddRawToObject (line 2147) | CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const ch...
function cJSON_AddObjectToObject (line 2159) | CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const...
function cJSON_AddArrayToObject (line 2171) | CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const ...
function cJSON_DetachItemViaPointer (line 2183) | CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * ...
function cJSON_DetachItemFromArray (line 2219) | CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
function cJSON_DeleteItemFromArray (line 2229) | CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
function cJSON_DetachItemFromObject (line 2234) | CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const ch...
function cJSON_DetachItemFromObjectCaseSensitive (line 2241) | CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *obj...
function cJSON_DeleteItemFromObject (line 2248) | CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char ...
function cJSON_DeleteItemFromObjectCaseSensitive (line 2253) | CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object...
function cJSON_InsertItemInArray (line 2259) | CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which...
function cJSON_ReplaceItemViaPointer (line 2288) | CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const paren...
function cJSON_ReplaceItemInArray (line 2337) | CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int whic...
function cJSON_bool (line 2347) | static cJSON_bool replace_item_in_object(cJSON *object, const char *stri...
function cJSON_ReplaceItemInObject (line 2365) | CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const ...
function cJSON_ReplaceItemInObjectCaseSensitive (line 2370) | CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *o...
function cJSON_CreateNull (line 2376) | CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
function cJSON_CreateTrue (line 2387) | CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
function cJSON_CreateFalse (line 2398) | CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
function cJSON_CreateBool (line 2409) | CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)
function cJSON_CreateNumber (line 2420) | CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
function cJSON_CreateString (line 2446) | CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
function cJSON_CreateStringReference (line 2463) | CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
function cJSON_CreateObjectReference (line 2475) | CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
function cJSON_CreateArrayReference (line 2486) | CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
function cJSON_CreateRaw (line 2496) | CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
function cJSON_CreateArray (line 2513) | CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
function cJSON_CreateObject (line 2524) | CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
function cJSON_CreateIntArray (line 2536) | CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
function cJSON_CreateFloatArray (line 2576) | CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int c...
function cJSON_CreateDoubleArray (line 2616) | CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int...
function cJSON_CreateStringArray (line 2656) | CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings...
function cJSON_Duplicate (line 2697) | CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recu...
function skip_oneline_comment (line 2780) | static void skip_oneline_comment(char **input)
function skip_multiline_comment (line 2793) | static void skip_multiline_comment(char **input)
function minify_string (line 2807) | static void minify_string(char **input, char **output) {
function cJSON_Minify (line 2829) | CJSON_PUBLIC(void) cJSON_Minify(char *json)
function cJSON_IsInvalid (line 2877) | CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
function cJSON_IsFalse (line 2887) | CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
function cJSON_IsTrue (line 2897) | CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
function cJSON_IsBool (line 2908) | CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
function cJSON_IsNull (line 2917) | CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
function cJSON_IsNumber (line 2927) | CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
function cJSON_IsString (line 2937) | CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
function cJSON_IsArray (line 2947) | CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
function cJSON_IsObject (line 2957) | CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
function cJSON_IsRaw (line 2967) | CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
function cJSON_Compare (line 2977) | CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSO...
function cJSON_malloc (line 3102) | CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
function cJSON_free (line 3107) | CJSON_PUBLIC(void) cJSON_free(void *object)
FILE: examples/jsonrpc/cJSON.h
type cJSON (line 103) | typedef struct cJSON
type cJSON_Hooks (line 125) | typedef struct cJSON_Hooks
type cJSON_bool (line 132) | typedef int cJSON_bool;
FILE: examples/jsonrpc/handler.h
function error_response (line 6) | void error_response(cJSON* jres, int code, const char* message) {
function not_found (line 13) | void not_found(cJSON* jreq, cJSON* jres) {
function bad_request (line 17) | void bad_request(cJSON* jreq, cJSON* jres) {
function calc_add (line 21) | void calc_add(cJSON* jreq, cJSON* jres) {
function calc_sub (line 35) | void calc_sub(cJSON* jreq, cJSON* jres) {
function calc_mul (line 49) | void calc_mul(cJSON* jreq, cJSON* jres) {
function calc_div (line 63) | void calc_div(cJSON* jreq, cJSON* jres) {
FILE: examples/jsonrpc/jsonrpc_client.c
function on_close (line 22) | static void on_close(hio_t* io) {
function on_recv (line 33) | static void on_recv(hio_t* io, void* readbuf, int readbytes) {
function on_connect (line 55) | static void on_connect(hio_t* io) {
function jsonrpc_call (line 83) | static int jsonrpc_call(hloop_t* loop, const char* host, int port, const...
function main (line 107) | int main(int argc, char** argv) {
FILE: examples/jsonrpc/jsonrpc_server.c
function on_close (line 31) | static void on_close(hio_t* io) {
function on_recv (line 35) | static void on_recv(hio_t* io, void* readbuf, int readbytes) {
function on_accept (line 84) | static void on_accept(hio_t* io) {
function main (line 100) | int main(int argc, char** argv) {
FILE: examples/jsonrpc/router.h
type jsonrpc_router (line 8) | typedef struct {
FILE: examples/kcptun/client/main.cpp
function print_version (line 43) | static void print_version() {
function print_help (line 47) | static void print_help() {
type kcp_ctx_s (line 68) | struct kcp_ctx_s {
function send_hearbeat (line 85) | static void send_hearbeat(htimer_t* timer) {
function on_close (line 96) | static void on_close(hio_t* io) {
function on_recv (line 130) | static void on_recv(hio_t* io, void* buf, int readbytes) {
function on_accept (line 150) | static void on_accept(hio_t* io) {
function on_kcp_recvfrom (line 189) | static void on_kcp_recvfrom(hio_t* io, void* buf, int readbytes) {
function main (line 242) | int main(int argc, char** argv) {
FILE: examples/kcptun/server/main.cpp
function print_version (line 42) | static void print_version() {
function print_help (line 46) | static void print_help() {
function on_close (line 84) | static void on_close(hio_t* io) {
function on_recv (line 118) | static void on_recv(hio_t* io, void* buf, int readbytes) {
function on_connect (line 138) | static void on_connect(hio_t* io) {
function on_kcp_recvfrom (line 162) | static void on_kcp_recvfrom(hio_t* io, void* buf, int readbytes) {
function main (line 219) | int main(int argc, char** argv) {
FILE: examples/kcptun/smux/smux.cpp
function smux_frame_pack (line 5) | int smux_frame_pack(const smux_frame_t* frame, void* buf, int len) {
function smux_frame_unpack (line 45) | int smux_frame_unpack(smux_frame_t* frame, const void* buf, int len) {
FILE: examples/kcptun/smux/smux.h
type smux_cmd_e (line 17) | typedef enum {
type smux_head_t (line 27) | typedef struct {
type smux_frame_t (line 36) | typedef struct {
function smux_package_length (line 41) | static inline unsigned int smux_package_length(const smux_head_t* head) {
function smux_head_init (line 45) | static inline void smux_head_init(smux_head_t* head) {
function smux_frame_init (line 52) | static inline void smux_frame_init(smux_frame_t* frame) {
type smux_stream_t (line 76) | typedef struct {
function smux_stream_output (line 86) | static inline int smux_stream_output(smux_stream_t* stream, smux_frame_t...
function smux_stream_output (line 90) | static inline int smux_stream_output(smux_stream_t* stream, smux_cmd_e c...
function smux_stream_input (line 99) | static inline int smux_stream_input(smux_stream_t* stream, const void* b...
type smux_session_t (line 103) | typedef struct {
function smux_stream_t (line 122) | static inline smux_stream_t* smux_session_get_stream(smux_session_t* ses...
function smux_session_close_stream (line 130) | static inline void smux_session_close_stream(smux_session_t* session, ui...
FILE: examples/mqtt/mqtt_client_test.cpp
function main (line 25) | int main(int argc, char** argv) {
FILE: examples/mqtt/mqtt_pub.c
function on_mqtt (line 35) | static void on_mqtt(mqtt_client_t* cli, int type) {
function mqtt_publish (line 83) | static int mqtt_publish(const char* host, int port, const char* topic, c...
function main (line 123) | int main(int argc, char** argv) {
FILE: examples/mqtt/mqtt_sub.c
function handle_message (line 35) | static void handle_message(mqtt_client_t* cli, mqtt_message_t* msg) {
function on_mqtt (line 40) | static void on_mqtt(mqtt_client_t* cli, int type) {
function mqtt_subscribe (line 73) | static int mqtt_subscribe(const char* host, int port, const char* topic) {
function main (line 104) | int main(int argc, char** argv) {
FILE: examples/multi-thread/multi-acceptor-processes.c
function on_close (line 21) | static void on_close(hio_t* io) {
function on_recv (line 25) | static void on_recv(hio_t* io, void* buf, int readbytes) {
function on_accept (line 30) | static void on_accept(hio_t* io) {
function loop_proc (line 44) | static void loop_proc(void* userdata) {
function main (line 59) | int main(int argc, char** argv) {
FILE: examples/multi-thread/multi-acceptor-threads.c
function on_close (line 20) | static void on_close(hio_t* io) {
function on_recv (line 24) | static void on_recv(hio_t* io, void* buf, int readbytes) {
function on_accept (line 29) | static void on_accept(hio_t* io) {
function HTHREAD_ROUTINE (line 43) | static HTHREAD_ROUTINE(loop_thread) {
function main (line 59) | int main(int argc, char** argv) {
FILE: examples/multi-thread/one-acceptor-multi-workers.c
function hloop_t (line 20) | static hloop_t* get_next_loop() {
function on_close (line 28) | static void on_close(hio_t* io) {
function on_recv (line 32) | static void on_recv(hio_t* io, void* buf, int readbytes) {
function new_conn_event (line 37) | static void new_conn_event(hevent_t* ev) {
function on_accept (line 55) | static void on_accept(hio_t* io) {
function HTHREAD_ROUTINE (line 67) | static HTHREAD_ROUTINE(worker_thread) {
function HTHREAD_ROUTINE (line 73) | static HTHREAD_ROUTINE(accept_thread) {
function main (line 83) | int main(int argc, char** argv) {
FILE: examples/nc.c
function send_heartbeat (line 53) | static void send_heartbeat(hio_t* io) {
function on_recv (line 59) | static void on_recv(hio_t* io, void* buf, int readbytes) {
function on_stdin (line 84) | static void on_stdin(hio_t* io, void* buf, int readbytes) {
function on_close (line 135) | static void on_close(hio_t* io) {
function on_connect (line 140) | static void on_connect(hio_t* io) {
function main (line 155) | int main(int argc, char** argv) {
FILE: examples/nmap/main.cpp
function host_discover_task (line 10) | int host_discover_task(std::string segment, void* nmap) {
function main (line 15) | int main(int argc, char* argv[]) {
FILE: examples/nmap/nmap.cpp
type nmap_ctx_s (line 12) | struct nmap_ctx_s {
function on_idle (line 20) | static void on_idle(hidle_t* idle) {
function on_timer (line 30) | static void on_timer(htimer_t* timer) {
function on_recvfrom (line 35) | static void on_recvfrom(hio_t* io, void* buf, int readbytes) {
function nmap_discover (line 62) | int nmap_discover(Nmap* nmap) {
function segment_discover (line 143) | int segment_discover(const char* segment16, Nmap* nmap) {
function host_discover (line 160) | int host_discover(const char* segment24, Nmap* nmap) {
FILE: examples/nmap/nmap.h
type std (line 8) | typedef std::map<uint32_t, int> Nmap;
FILE: examples/pipe_test.c
function on_read (line 14) | static void on_read(hio_t* io, void* buf, int readbytes) {
function on_timer_write (line 18) | static void on_timer_write(htimer_t* timer) {
function on_timer_stop (line 25) | static void on_timer_stop(htimer_t* timer) {
function main (line 31) | int main(int argc, char** argv) {
FILE: examples/protorpc/handler/calc.h
function calc_add (line 8) | void calc_add(const protorpc::Request& req, protorpc::Response* res) {
function calc_sub (line 25) | void calc_sub(const protorpc::Request& req, protorpc::Response* res) {
function calc_mul (line 42) | void calc_mul(const protorpc::Request& req, protorpc::Response* res) {
function calc_div (line 59) | void calc_div(const protorpc::Request& req, protorpc::Response* res) {
FILE: examples/protorpc/handler/handler.h
function error_response (line 6) | void error_response(protorpc::Response* res, int code, const std::string...
function not_found (line 11) | void not_found(const protorpc::Request& req, protorpc::Response* res) {
function bad_request (line 15) | void bad_request(const protorpc::Request& req, protorpc::Response* res) {
FILE: examples/protorpc/handler/login.h
function login (line 8) | void login(const protorpc::Request& req, protorpc::Response* res) {
FILE: examples/protorpc/protorpc.c
function protorpc_pack (line 5) | int protorpc_pack(const protorpc_message* msg, void* buf, int len) {
function protorpc_unpack (line 36) | int protorpc_unpack(protorpc_message* msg, const void* buf, int len) {
FILE: examples/protorpc/protorpc.h
type protorpc_head (line 17) | typedef struct {
type protorpc_message (line 27) | typedef struct {
function protorpc_package_length (line 32) | static inline unsigned int protorpc_package_length(const protorpc_head* ...
function protorpc_head_init (line 36) | static inline void protorpc_head_init(protorpc_head* head) {
function protorpc_message_init (line 44) | static inline void protorpc_message_init(protorpc_message* msg) {
function protorpc_head_check (line 49) | static inline int protorpc_head_check(protorpc_head* head) {
FILE: examples/protorpc/protorpc_client.cpp
class ProtobufRAII (line 24) | class ProtobufRAII {
method ProtobufRAII (line 26) | ProtobufRAII() {
type protorpc (line 34) | namespace protorpc {
type ProtoRpcResult (line 38) | enum ProtoRpcResult {
class ProtoRpcContext (line 46) | class ProtoRpcContext {
class ProtoRpcClient (line 53) | class ProtoRpcClient : public TcpClient {
method ProtoRpcClient (line 55) | ProtoRpcClient() : TcpClient()
method connect (line 122) | int connect(int port, const char* host = "127.0.0.1", bool wait_conn...
method isConnected (line 137) | bool isConnected() {
method call (line 141) | protorpc::ResponsePtr call(protorpc::RequestPtr& req, int timeout_ms...
method calc (line 190) | int calc(const char* method, int num1, int num2, int& out) {
method login (line 212) | int login(const protorpc::LoginParam& param, protorpc::LoginResult* ...
type ConnectStatus (line 229) | enum ConnectStatus {
function main (line 241) | int main(int argc, char** argv) {
FILE: examples/protorpc/protorpc_server.cpp
class ProtobufRAII (line 21) | class ProtobufRAII {
method ProtobufRAII (line 23) | ProtobufRAII() {
class ProtoRpcServer (line 40) | class ProtoRpcServer : public TcpServer {
method ProtoRpcServer (line 42) | ProtoRpcServer() : TcpServer()
method listen (line 65) | int listen(int port) { return createsocket(port); }
method handleMessage (line 68) | static void handleMessage(const SocketChannelPtr& channel, Buffer* buf) {
function main (line 123) | int main(int argc, char** argv) {
FILE: examples/protorpc/router.h
type protorpc_router (line 8) | typedef struct {
FILE: examples/socks5_proxy_server.c
type socks5_auth_method (line 29) | typedef enum {
type socks5_command (line 35) | typedef enum {
type socks5_addr_type (line 41) | typedef enum {
type socks5_reply_code (line 47) | typedef enum {
type socks5_state_e (line 59) | typedef enum {
type socks5_conn_t (line 76) | typedef struct {
function on_upstream_connect (line 102) | static void on_upstream_connect(hio_t* upstream_io) {
function on_close (line 124) | static void on_close(hio_t* io) {
function on_recv (line 134) | static void on_recv(hio_t* io, void* buf, int readbytes) {
function on_accept (line 366) | static void on_accept(hio_t* io) {
function main (line 388) | int main(int argc, char** argv) {
FILE: examples/tcp_chat_server.c
type chatroom_t (line 23) | typedef struct chatroom_s {
type connection_t (line 30) | typedef struct connection_s {
function join (line 42) | void join(chatroom_t* room, connection_t* conn) {
function leave (line 63) | void leave(chatroom_t* room, connection_t* conn) {
function broadcast (line 71) | void broadcast(chatroom_t* room, const char* msg, int msglen) {
function on_close (line 81) | static void on_close(hio_t* io) {
function on_recv (line 93) | static void on_recv(hio_t* io, void* buf, int readbytes) {
function on_accept (line 110) | static void on_accept(hio_t* io) {
function main (line 132) | int main(int argc, char** argv) {
FILE: examples/tcp_client_test.c
type tcp_client_t (line 22) | typedef struct tcp_client_s {
function reconnect_timer_cb (line 64) | static void reconnect_timer_cb(htimer_t* timer) {
function on_close (line 71) | static void on_close(hio_t* io) {
function on_message (line 84) | static void on_message(hio_t* io, void* buf, int len) {
function on_connect (line 90) | static void on_connect(hio_t* io) {
function tcp_client_t (line 112) | tcp_client_t* tcp_client_new(hloop_t* loop) {
function tcp_client_free (line 126) | void tcp_client_free(tcp_client_t* cli) {
function tcp_client_run (line 137) | void tcp_client_run (tcp_client_t* cli) {
function tcp_client_stop (line 142) | void tcp_client_stop(tcp_client_t* cli) {
function tcp_client_set_ssl_ctx (line 147) | int tcp_client_set_ssl_ctx(tcp_client_t* cli, hssl_ctx_t ssl_ctx) {
function tcp_client_new_ssl_ctx (line 153) | int tcp_client_new_ssl_ctx(tcp_client_t* cli, hssl_ctx_opt_t* opt) {
function tcp_client_set_reconnect (line 161) | int tcp_client_set_reconnect(tcp_client_t* cli, reconn_setting_t* reconn) {
function tcp_client_reconnect (line 173) | int tcp_client_reconnect(tcp_client_t* cli) {
function tcp_client_connect (line 178) | int tcp_client_connect(tcp_client_t* cli, const char* host, int port, in...
function tcp_client_disconnect (line 201) | int tcp_client_disconnect(tcp_client_t* cli) {
function tcp_client_is_connected (line 208) | bool tcp_client_is_connected(tcp_client_t* cli) {
function tcp_client_send (line 212) | int tcp_client_send(tcp_client_t* cli, const void* buf, int len) {
function main (line 222) | int main(int argc, char** argv) {
FILE: examples/tcp_echo_server.c
function on_close (line 38) | static void on_close(hio_t* io) {
function on_recv (line 42) | static void on_recv(hio_t* io, void* buf, int readbytes) {
function on_accept (line 67) | static void on_accept(hio_t* io) {
function main (line 95) | int main(int argc, char** argv) {
FILE: examples/tcp_proxy_server.c
function on_accept (line 39) | static void on_accept(hio_t* io) {
function main (line 53) | int main(int argc, char** argv) {
FILE: examples/tinyhttpd.c
type http_state_e (line 52) | typedef enum {
type http_msg_t (line 63) | typedef struct {
type http_conn_t (line 91) | typedef struct {
function update_date (line 102) | static void update_date(htimer_t* timer) {
function http_response_dump (line 107) | static int http_response_dump(http_msg_t* msg, char* buf, int len) {
function http_reply (line 133) | static int http_reply(http_conn_t* conn,
function http_send_file (line 158) | static void http_send_file(http_conn_t* conn) {
function on_write (line 178) | static void on_write(hio_t* io, const void* buf, int writebytes) {
function http_serve_file (line 185) | static int http_serve_file(http_conn_t* conn) {
function parse_http_request_line (line 216) | static bool parse_http_request_line(http_conn_t* conn, char* buf, int le...
function parse_http_head (line 226) | static bool parse_http_head(http_conn_t* conn, char* buf, int len) {
function on_request (line 252) | static int on_request(http_conn_t* conn) {
function on_close (line 279) | static void on_close(hio_t* io) {
function on_recv (line 295) | static void on_recv(hio_t* io, void* buf, int readbytes) {
function new_conn_event (line 385) | static void new_conn_event(hevent_t* ev) {
function hloop_t (line 413) | static hloop_t* get_next_loop() {
function on_accept (line 421) | static void on_accept(hio_t* io) {
function HTHREAD_ROUTINE (line 433) | static HTHREAD_ROUTINE(worker_thread) {
function HTHREAD_ROUTINE (line 439) | static HTHREAD_ROUTINE(accept_thread) {
function main (line 453) | int main(int argc, char** argv) {
FILE: examples/tinyproxyd.c
type http_state_e (line 45) | typedef enum {
type http_msg_t (line 56) | typedef struct {
type http_conn_t (line 85) | typedef struct {
function http_request_dump (line 92) | static int http_request_dump(http_conn_t* conn, char* buf, int len) {
function parse_http_request_line (line 132) | static bool parse_http_request_line(http_conn_t* conn, char* buf, int le...
function parse_http_head (line 142) | static bool parse_http_head(http_conn_t* conn, char* buf, int len) {
function on_upstream_connect (line 168) | static void on_upstream_connect(hio_t* upstream_io) {
function on_head_end (line 195) | static int on_head_end(http_conn_t* conn) {
function on_body (line 239) | static int on_body(http_conn_t* conn, void* buf, int readbytes) {
function on_request (line 247) | static int on_request(http_conn_t* conn) {
function on_close (line 257) | static void on_close(hio_t* io) {
function on_recv (line 267) | static void on_recv(hio_t* io, void* buf, int readbytes) {
function new_conn_event (line 388) | static void new_conn_event(hevent_t* ev) {
function hloop_t (line 416) | static hloop_t* get_next_loop() {
function on_accept (line 424) | static void on_accept(hio_t* io) {
function HTHREAD_ROUTINE (line 436) | static HTHREAD_ROUTINE(worker_thread) {
function HTHREAD_ROUTINE (line 442) | static HTHREAD_ROUTINE(accept_thread) {
function main (line 457) | int main(int argc, char** argv) {
FILE: examples/udp_echo_server.c
function on_recvfrom (line 25) | static void on_recvfrom(hio_t* io, void* buf, int readbytes) {
function main (line 46) | int main(int argc, char** argv) {
FILE: examples/udp_proxy_server.c
function main (line 22) | int main(int argc, char** argv) {
FILE: examples/websocket_client_test.cpp
class MyWebSocketClient (line 17) | class MyWebSocketClient : public WebSocketClient {
method MyWebSocketClient (line 19) | MyWebSocketClient(EventLoopPtr loop = NULL) : WebSocketClient(loop) {}
method connect (line 22) | int connect(const char* url) {
function TestMultiClientsRunInOneEventLoop (line 65) | int TestMultiClientsRunInOneEventLoop(const char* url, int nclients) {
function main (line 84) | int main(int argc, char** argv) {
FILE: examples/websocket_server_test.cpp
class MyContext (line 33) | class MyContext {
method MyContext (line 35) | MyContext() {
method handleMessage (line 43) | int handleMessage(const std::string& msg, enum ws_opcode opcode) {
function main (line 52) | int main(int argc, char** argv) {
FILE: examples/wget.cpp
function wget (line 13) | static int wget(const char* url, const char* filepath, wget_progress_cb ...
function main (line 129) | int main(int argc, char** argv) {
FILE: examples/wrk.cpp
type connection_s (line 50) | struct connection_s {
method connection_s (line 61) | connection_s()
method SendRequest (line 74) | void SendRequest() {
method RecvResponse (line 81) | bool RecvResponse(const char* data, int size) {
function print_help (line 107) | static void print_help() {
function print_cmd (line 112) | static void print_cmd() {
function print_result (line 117) | static void print_result() {
function on_close (line 160) | static void on_close(hio_t* io) {
function on_recv (line 173) | static void on_recv(hio_t* io, void* buf, int readbytes) {
function send_heartbeat (line 182) | static void send_heartbeat(hio_t* io) {
function on_connect (line 187) | static void on_connect(hio_t* io) {
function start_connect (line 205) | static void start_connect(hloop_t* loop, connection_t* conn) {
function start_reconnect (line 222) | static void start_reconnect(hio_t* io) {
function main (line 228) | int main(int argc, char** argv) {
FILE: http/Http1Parser.cpp
function on_url (line 41) | int on_url(http_parser* parser, const char *at, size_t length) {
function on_status (line 49) | int on_status(http_parser* parser, const char *at, size_t length) {
function on_header_field (line 56) | int on_header_field(http_parser* parser, const char *at, size_t length) {
function on_header_value (line 67) | int on_header_value(http_parser* parser, const char *at, size_t length) {
function on_body (line 75) | int on_body(http_parser* parser, const char *at, size_t length) {
function on_message_begin (line 86) | int on_message_begin(http_parser* parser) {
function on_headers_complete (line 94) | int on_headers_complete(http_parser* parser) {
function on_message_complete (line 134) | int on_message_complete(http_parser* parser) {
function on_chunk_header (line 142) | int on_chunk_header(http_parser* parser) {
function on_chunk_complete (line 155) | int on_chunk_complete(http_parser* parser) {
FILE: http/Http1Parser.h
function class (line 7) | class Http1Parser : public HttpParser {
FILE: http/Http2Parser.cpp
function nghttp2_nv (line 5) | static nghttp2_nv make_nv(const char* name, const char* value) {
function nghttp2_nv (line 15) | static nghttp2_nv make_nv2(const char* name, const char* value,
function print_frame_hd (line 25) | static void print_frame_hd(const nghttp2_frame_hd* hd) {
function on_header_callback (line 313) | int on_header_callback(nghttp2_session *session,
function on_data_chunk_recv_callback (line 360) | int on_data_chunk_recv_callback(nghttp2_session *session,
function on_frame_recv_callback (line 387) | int on_frame_recv_callback(nghttp2_session *session,
FILE: http/Http2Parser.h
type http2_session_state (line 11) | enum http2_session_state {
function class (line 29) | class Http2Parser : public HttpParser {
FILE: http/HttpMessage.cpp
function HV_EXPORT (line 251) | HV_EXPORT int64_t HttpMessage::Get(const char* key, int64_t defvalue) {
function HV_EXPORT (line 282) | HV_EXPORT int HttpMessage::Get(const char* key, int defvalue) {
function HV_EXPORT (line 287) | HV_EXPORT double HttpMessage::Get(const char* key, double defvalue) {
function HV_EXPORT (line 314) | HV_EXPORT float HttpMessage::Get(const char* key, float defvalue) {
function HV_EXPORT (line 319) | HV_EXPORT bool HttpMessage::Get(const char* key, bool defvalue) {
function HttpCookie (line 477) | const HttpCookie& HttpMessage::GetCookie(const std::string& name) {
FILE: http/HttpMessage.h
function HttpCookie (line 51) | struct HV_EXPORT HttpCookie {
type std (line 83) | typedef std::map<std::string, std::string, hv::StringCaseLess> http_hea...
type std (line 84) | typedef std::vector<HttpCookie> http_coo...
type std (line 85) | typedef std::string http_body;
function class (line 91) | class HV_EXPORT HttpMessage {
function hv (line 165) | const hv::Json& GetJson() {
function SetFormFile (line 177) | void SetFormFile(const char* name, const char* filepath) {
function FormFile (line 180) | int FormFile(const char* name, const char* filepath) {
function hv (line 185) | const hv::MultiPart& GetForm() {
function SaveFormFile (line 198) | int SaveFormFile(const char* name, const char* path) {
function hv (line 231) | const hv::KeyValue& GetUrlEncoded() {
function ContentLength (line 293) | size_t ContentLength() {
function http_content_type (line 300) | http_content_type ContentType() {
function SetContentType (line 306) | void SetContentType(http_content_type type) {
function SetContentType (line 309) | void SetContentType(const char* type) {
function SetContentTypeByFilename (line 312) | void SetContentTypeByFilename(const char* filepath) {
function String (line 322) | int String(const std::string& str) {
function File (line 342) | int File(const char* filepath) {
function SaveFile (line 352) | int SaveFile(const char* filepath) {
function SetMethod (line 398) | void SetMethod(const char* method) {
function IsHttps (line 406) | bool IsHttps() {
function SetUrl (line 412) | void SetUrl(const char* url) {
function std (line 415) | const std::string& Url() {
function IsProxy (line 447) | bool IsProxy() { return proxy; }
function SetTimeout (line 454) | void SetTimeout(int sec) { timeout = sec; }
function SetConnectTimeout (line 455) | void SetConnectTimeout(int sec) { connect_timeout = sec; }
function SetRetry (line 460) | void SetRetry(int count = DEFAULT_HTTP_FAIL_RETRY_COUNT,
function Cancel (line 465) | void Cancel() { cancel = 1; }
function IsCanceled (line 466) | bool IsCanceled() { return cancel == 1; }
function Redirect (line 491) | int Redirect(const std::string& location, http_status status = HTTP_STAT...
type std (line 498) | typedef std::shared_ptr<HttpRequest> HttpRequestPtr;
type std (line 499) | typedef std::shared_ptr<HttpResponse> HttpResponsePtr;
type std (line 500) | typedef std::function<void(const HttpResponsePtr&)> HttpResponseCallback;
FILE: http/HttpParser.cpp
function HttpParser (line 7) | HttpParser* HttpParser::New(http_session_type type, http_version version) {
FILE: http/HttpParser.h
function class (line 7) | class HV_EXPORT HttpParser {
type std (line 51) | typedef std::shared_ptr<HttpParser> HttpParserPtr;
FILE: http/WebSocketChannel.cpp
type hv (line 3) | namespace hv {
type ws_opcode (line 5) | enum ws_opcode
type ws_opcode (line 24) | enum ws_opcode
type ws_opcode (line 66) | enum ws_opcode
FILE: http/WebSocketChannel.h
function namespace (line 11) | namespace hv {
type std (line 53) | typedef std::shared_ptr<hv::WebSocketChannel> WebSocketChannelPtr;
FILE: http/WebSocketParser.cpp
function on_frame_header (line 8) | static int on_frame_header(websocket_parser* parser) {
function on_frame_body (line 28) | static int on_frame_body(websocket_parser* parser, const char * at, size...
function on_frame_end (line 39) | static int on_frame_end(websocket_parser* parser) {
FILE: http/WebSocketParser.h
type websocket_parser_state (line 10) | enum websocket_parser_state {
type websocket_parser (line 18) | struct websocket_parser
function class (line 19) | class HV_EXPORT WebSocketParser {
type std (line 33) | typedef std::shared_ptr<WebSocketParser> WebSocketParserPtr;
FILE: http/client/AsyncHttpClient.cpp
type hv (line 3) | namespace hv {
FILE: http/client/AsyncHttpClient.h
function namespace (line 13) | namespace hv {
function send (line 118) | int send(const HttpClientTaskPtr& task) {
function SocketChannelPtr (line 135) | const SocketChannelPtr& getChannel(int fd) {
function SocketChannelPtr (line 140) | const SocketChannelPtr& addChannel(hio_t* io) {
function removeChannel (line 148) | void removeChannel(const SocketChannelPtr& channel) {
FILE: http/client/HttpClient.cpp
type http_client_s (line 22) | struct http_client_s {
method http_client_s (line 51) | http_client_s() {
method Close (line 76) | void Close() {
function http_client_t (line 91) | http_client_t* http_client_new(const char* host, int port, int https) {
function http_client_del (line 100) | int http_client_del(http_client_t* cli) {
function http_client_set_timeout (line 106) | int http_client_set_timeout(http_client_t* cli, int timeout) {
function http_client_set_ssl_ctx (line 111) | int http_client_set_ssl_ctx(http_client_t* cli, hssl_ctx_t ssl_ctx) {
function http_client_new_ssl_ctx (line 116) | int http_client_new_ssl_ctx(http_client_t* cli, hssl_ctx_opt_t* opt) {
function http_client_clear_headers (line 124) | int http_client_clear_headers(http_client_t* cli) {
function http_client_set_header (line 129) | int http_client_set_header(http_client_t* cli, const char* key, const ch...
function http_client_del_header (line 134) | int http_client_del_header(http_client_t* cli, const char* key) {
function http_client_set_http_proxy (line 150) | int http_client_set_http_proxy(http_client_t* cli, const char* host, int...
function http_client_set_https_proxy (line 156) | int http_client_set_https_proxy(http_client_t* cli, const char* host, in...
function http_client_add_no_proxy (line 162) | int http_client_add_no_proxy(http_client_t* cli, const char* host) {
function http_client_make_request (line 167) | static int http_client_make_request(http_client_t* cli, HttpRequest* req) {
function http_client_connect (line 208) | int http_client_connect(http_client_t* cli, const char* host, int port, ...
function http_client_close (line 270) | int http_client_close(http_client_t* cli) {
function http_client_send_data (line 276) | int http_client_send_data(http_client_t* cli, const char* data, int size) {
function http_client_recv_data (line 286) | int http_client_recv_data(http_client_t* cli, char* data, int size) {
function http_client_exec (line 296) | static int http_client_exec(http_client_t* cli, HttpRequest* req, HttpRe...
function http_client_send_header (line 424) | int http_client_send_header(http_client_t* cli, HttpRequest* req) {
function http_client_recv_response (line 432) | int http_client_recv_response(http_client_t* cli, HttpResponse* resp) {
function s_header_cb (line 460) | static size_t s_header_cb(char* buf, size_t size, size_t cnt, void* user...
function s_body_cb (line 497) | static size_t s_body_cb(char* buf, size_t size, size_t cnt, void *userda...
function http_client_exec_curl (line 514) | static int http_client_exec_curl(http_client_t* cli, HttpRequest* req, H...
function http_client_redirect (line 655) | static int http_client_redirect(HttpRequest* req, HttpResponse* resp) {
function http_client_send (line 668) | int http_client_send(http_client_t* cli, HttpRequest* req, HttpResponse*...
function http_client_send (line 689) | int http_client_send(HttpRequest* req, HttpResponse* resp) {
function http_client_exec_async (line 697) | static int http_client_exec_async(http_client_t* cli, HttpRequestPtr req...
function http_client_send_async (line 709) | int http_client_send_async(http_client_t* cli, HttpRequestPtr req, HttpR...
function hv_destroy_default_async_http_client (line 716) | static void hv_destroy_default_async_http_client() {
function http_client_t (line 723) | static http_client_t* hv_default_async_http_client() {
function http_client_send_async (line 738) | int http_client_send_async(HttpRequestPtr req, HttpResponseCallback resp...
FILE: http/client/HttpClient.h
type http_client_t (line 30) | typedef struct http_client_s http_client_t;
function namespace (line 80) | namespace hv {
function sendHeader (line 142) | int sendHeader(HttpRequest* req) {
function sendData (line 145) | int sendData(const char* data, int size) {
function recvData (line 148) | int recvData(char* data, int size) {
function recvResponse (line 151) | int recvResponse(HttpResponse* resp) {
function close (line 154) | int close() {
type http_client_deleter (line 159) | struct http_client_deleter {
FILE: http/client/WebSocketClient.cpp
type hv (line 8) | namespace hv {
type ws_opcode (line 143) | enum ws_opcode
type ws_opcode (line 212) | enum ws_opcode
FILE: http/client/WebSocketClient.h
function namespace (line 16) | namespace hv {
FILE: http/client/axios.h
function namespace (line 65) | namespace axios {
function HV_INLINE (line 128) | HV_INLINE Response axios(const char* req_str, http_method method = HTTP_...
function HV_INLINE (line 141) | HV_INLINE Response get(const char* url, const json& jreq) {
function HV_INLINE (line 149) | HV_INLINE Response post(const char* url, const json& jreq) {
function HV_INLINE (line 157) | HV_INLINE Response put(const char* url, const json& jreq) {
function HV_INLINE (line 165) | HV_INLINE Response patch(const char* url, const json& jreq) {
function HV_INLINE (line 169) | HV_INLINE Response patch(const char* url, const char* req_str = nullptr) {
function HV_INLINE (line 182) | HV_INLINE int axios(const json& jreq, ResponseCallback resp_cb) {
function HV_INLINE (line 187) | HV_INLINE int axios(const char* req_str, ResponseCallback resp_cb) {
FILE: http/client/requests.h
type HttpRequestPtr (line 38) | typedef HttpRequestPtr Request;
type HttpResponsePtr (line 39) | typedef HttpResponsePtr Response;
type HttpResponseCallback (line 40) | typedef HttpResponseCallback ResponseCallback;
function HV_INLINE (line 42) | HV_INLINE Response request(Request req) {
function HV_INLINE (line 48) | HV_INLINE Response request(http_method method, const char* url, const ht...
function HV_INLINE (line 86) | HV_INLINE int async(Request req, ResponseCallback resp_cb) {
function HV_INLINE (line 91) | HV_INLINE Response uploadFile(const char* url, const char* filepath, htt...
function HV_INLINE (line 104) | HV_INLINE Response uploadFormFile(const char* url, const char* name, con...
type std (line 274) | typedef std::function<void(size_t received_bytes, size_t total_bytes)> d...
FILE: http/grpcdef.h
type grpc_message_hd (line 13) | typedef struct {
type grpc_message (line 18) | typedef struct {
function grpc_message_hd_pack (line 24) | static inline void grpc_message_hd_pack(const grpc_message_hd* hd, unsig...
function grpc_message_hd_unpack (line 36) | static inline void grpc_message_hd_unpack(grpc_message_hd* hd, const uns...
type wire_type (line 50) | typedef enum {
type field_type (line 59) | typedef enum {
FILE: http/http2def.h
type http2_frame_type (line 20) | typedef enum {
type http2_flag (line 35) | typedef enum {
type http2_frame_hd (line 43) | typedef struct {
function http2_frame_hd_pack (line 50) | static inline void http2_frame_hd_pack(const http2_frame_hd* hd, unsigne...
function http2_frame_hd_unpack (line 66) | static inline void http2_frame_hd_unpack(const unsigned char* buf, http2...
FILE: http/http_content.cpp
function BEGIN_NAMESPACE_HV (line 7) | BEGIN_NAMESPACE_HV
function parse_query_params (line 22) | int parse_query_params(const char* query_string, QueryParams& query_para...
function dump_multipart (line 70) | std::string dump_multipart(MultiPart& mp, const char* boundary) {
type multipart_parser_state_e (line 112) | enum multipart_parser_state_e {
type multipart_parser_userdata (line 122) | struct multipart_parser_userdata {
method handle_header (line 132) | void handle_header() {
method handle_data (line 155) | void handle_data() {
function on_header_field (line 167) | static int on_header_field(multipart_parser* parser, const char *at, siz...
function on_header_value (line 175) | static int on_header_value(multipart_parser* parser, const char *at, siz...
function on_part_data (line 182) | static int on_part_data(multipart_parser* parser, const char *at, size_t...
function on_part_data_begin (line 189) | static int on_part_data_begin(multipart_parser* parser) {
function on_headers_complete (line 195) | static int on_headers_complete(multipart_parser* parser) {
function on_part_data_end (line 202) | static int on_part_data_end(multipart_parser* parser) {
function on_body_end (line 209) | static int on_body_end(multipart_parser* parser) {
function parse_multipart (line 215) | int parse_multipart(const std::string& str, MultiPart& mp, const char* b...
function dump_json (line 237) | std::string dump_json(const hv::Json& json, int indent) {
function parse_json (line 242) | int parse_json(const char* str, hv::Json& json, std::string& errmsg) {
FILE: http/http_content.h
function if (line 35) | struct FormData {
function FormData (line 53) | struct FormFile : public FormData {
type HV_MAP (line 63) | typedef HV_MAP<std::string, FormData> MultiPart;
FILE: http/http_parser.c
type state (line 279) | enum state
type header_states (line 365) | enum header_states
type http_host_state (line 397) | enum http_host_state
function parse_url_char (line 490) | static enum state
function http_parser_execute (line 638) | size_t http_parser_execute (http_parser *parser,
function http_message_needs_eof (line 2093) | int
function http_should_keep_alive (line 2116) | int
function http_parser_init (line 2134) | void
function http_parser_settings_init (line 2145) | void
type http_errno (line 2152) | enum http_errno
type http_errno (line 2158) | enum http_errno
function http_parse_host_char (line 2164) | static enum http_host_state
function http_parse_host (line 2246) | static int
function http_parser_url_init (line 2328) | void
function http_parser_parse_url (line 2333) | int
function http_parser_pause (line 2457) | void
function http_body_is_final (line 2472) | int
function http_parser_version (line 2477) | unsigned long
function http_parser_set_max_header_size (line 2484) | void
FILE: http/http_parser.h
type __int8 (line 37) | typedef __int8 int8_t;
type __int16 (line 39) | typedef __int16 int16_t;
type __int32 (line 41) | typedef __int32 int32_t;
type __int64 (line 43) | typedef __int64 int64_t;
type http_parser (line 67) | typedef struct http_parser http_parser;
type http_parser_settings (line 68) | typedef struct http_parser_settings http_parser_settings;
type flags (line 93) | enum flags
type http_errno (line 157) | enum http_errno {
type http_parser (line 167) | struct http_parser {
type http_parser_settings (line 198) | struct http_parser_settings {
type http_parser_url_fields (line 216) | enum http_parser_url_fields
type http_parser_url (line 235) | struct http_parser_url {
type http_parser_type (line 259) | enum http_parser_type
type http_errno (line 284) | enum http_errno
type http_errno (line 287) | enum http_errno
type http_parser_url (line 291) | struct http_parser_url
type http_parser_url (line 296) | struct http_parser_url
FILE: http/httpdef.c
function strstartswith (line 5) | static int strstartswith(const char* str, const char* start) {
type http_status (line 13) | enum http_status
type http_method (line 22) | enum http_method
type http_content_type (line 31) | enum http_content_type
function http_status_enum (line 40) | enum http_status http_status_enum(const char* str) {
function http_method_enum (line 50) | enum http_method http_method_enum(const char* str) {
function http_content_type_enum (line 60) | enum http_content_type http_content_type_enum(const char* str) {
type http_content_type (line 73) | enum http_content_type
function http_content_type_enum_by_suffix (line 95) | enum http_content_type http_content_type_enum_by_suffix(const char* str) {
FILE: http/httpdef.h
type http_version (line 9) | enum http_version { HTTP_V1 = 1, HTTP_V2 = 2 }
type http_session_type (line 10) | enum http_session_type { HTTP_CLIENT, HTTP_SERVER }
type http_parser_type (line 11) | enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH }
type http_parser_state (line 12) | enum http_parser_state {
type http_status (line 91) | enum http_status {
type http_method (line 154) | enum http_method {
type http_content_type (line 250) | enum http_content_type {
type http_status (line 281) | enum http_status
type http_method (line 282) | enum http_method
type http_content_type (line 283) | enum http_content_type
type http_content_type (line 289) | enum http_content_type
FILE: http/multipart_parser.c
function multipart_log (line 12) | static void multipart_log(const char * format, ...)
type multipart_parser (line 48) | struct multipart_parser {
type state (line 62) | enum state {
function multipart_parser (line 82) | multipart_parser* multipart_parser_init
function multipart_parser_free (line 101) | void multipart_parser_free(multipart_parser* p) {
function multipart_parser_set_data (line 105) | void multipart_parser_set_data(multipart_parser *p, void *data) {
function multipart_parser_execute (line 113) | size_t multipart_parser_execute(multipart_parser* p, const char *buf, si...
FILE: http/multipart_parser.h
type multipart_parser (line 16) | typedef struct multipart_parser multipart_parser;
type multipart_parser_settings (line 17) | typedef struct multipart_parser_settings multipart_parser_settings;
type multipart_parser_state (line 18) | typedef struct multipart_parser_state multipart_parser_state;
type multipart_parser_settings (line 23) | struct multipart_parser_settings {
FILE: http/server/FileCache.cpp
function file_cache_ptr (line 22) | file_cache_ptr FileCache::Open(const char* filepath, OpenParam* param) {
function file_cache_ptr (line 146) | file_cache_ptr FileCache::Get(const char* filepath) {
FILE: http/server/FileCache.h
type file_cache_s (line 17) | struct file_cache_s {
function resize_buf (line 45) | void resize_buf(int filesize) {
function prepend_header (line 51) | void prepend_header(const char* header, int len) {
type std (line 59) | typedef std::shared_ptr<file_cache_t> file_cache_ptr;
FILE: http/server/HttpContext.h
function namespace (line 8) | namespace hv {
type std (line 211) | typedef std::shared_ptr<hv::HttpContext> HttpContextPtr;
FILE: http/server/HttpHandler.cpp
type http_version (line 65) | enum http_version
type ws_opcode (line 175) | enum ws_opcode
function HttpContextPtr (line 219) | const HttpContextPtr& HttpHandler::context() {
FILE: http/server/HttpHandler.h
function class (line 11) | class HttpHandler {
FILE: http/server/HttpMiddleware.cpp
function BEGIN_NAMESPACE_HV (line 4) | BEGIN_NAMESPACE_HV
FILE: http/server/HttpMiddleware.h
function BEGIN_NAMESPACE_HV (line 7) | BEGIN_NAMESPACE_HV
FILE: http/server/HttpResponseWriter.cpp
type hv (line 3) | namespace hv {
FILE: http/server/HttpResponseWriter.h
function namespace (line 7) | namespace hv {
type std (line 98) | typedef std::shared_ptr<hv::HttpResponseWriter> HttpResponseWriterPtr;
FILE: http/server/HttpServer.cpp
type HttpServerPrivdata (line 17) | struct HttpServerPrivdata {
function on_recv (line 25) | static void on_recv(hio_t* io, void* buf, int readbytes) {
function on_close (line 37) | static void on_close(hio_t* io) {
function on_accept (line 50) | static void on_accept(hio_t* io) {
function loop_thread (line 95) | static void loop_thread(void* userdata) {
function loop_thread_stdcall (line 167) | static void WINAPI loop_thread_stdcall(void* userdata) {
function http_server_run (line 179) | int http_server_run(http_server_t* server, int wait) {
function http_server_stop (line 241) | int http_server_stop(http_server_t* server) {
type hv (line 292) | namespace hv {
FILE: http/server/HttpServer.h
function namespace (line 9) | namespace hv {
type http_server_s (line 16) | struct http_server_s {
function stop (line 156) | int stop() {
FILE: http/server/HttpService.cpp
type hv (line 6) | namespace hv {
FILE: http/server/HttpService.h
type std (line 40) | typedef std::function<int(HttpRequest* req, HttpResponse* resp)> ...
type std (line 42) | typedef std::function<void(const HttpRequestPtr& req, const HttpResponse...
type std (line 44) | typedef std::function<int(const HttpContextPtr& ctx)> ...
type std (line 46) | typedef std::function<int(const HttpContextPtr& ctx, http_parser_state s...
type http_handler (line 48) | struct http_handler {
function isNull (line 83) | bool isNull() {
function operator (line 89) | operator bool() {
type std (line 94) | typedef std::vector<http_handler> http_handlers;
type http_method_handler (line 96) | struct http_method_handler {
FILE: http/server/WebSocketServer.h
function namespace (line 15) | namespace hv {
FILE: http/server/http_page.cpp
function make_http_status_page (line 7) | void make_http_status_page(http_status status_code, std::string& page) {
function make_index_of_page (line 27) | void make_index_of_page(const char* dir, std::string& page, const char* ...
FILE: http/websocket_parser.c
type state (line 34) | enum state {
function websocket_parser_init (line 42) | void websocket_parser_init(websocket_parser * parser) {
function websocket_parser_settings_init (line 49) | void websocket_parser_settings_init(websocket_parser_settings *settings) {
function websocket_parser_execute (line 53) | size_t websocket_parser_execute(websocket_parser *parser, const websocke...
function websocket_parser_decode (line 173) | void websocket_parser_decode(char * dst, const char * src, size_t len, w...
function websocket_decode (line 182) | uint8_t websocket_decode(char * dst, const char * src, size_t len, const...
function websocket_calc_frame_size (line 191) | size_t websocket_calc_frame_size(websocket_flags flags, size_t data_len) {
function websocket_build_frame (line 207) | size_t websocket_build_frame(char * frame, websocket_flags flags, const ...
FILE: http/websocket_parser.h
type __int8 (line 13) | typedef __int8 int8_t;
type __int16 (line 15) | typedef __int16 int16_t;
type __int32 (line 17) | typedef __int32 int32_t;
type __int64 (line 19) | typedef __int64 int64_t;
type websocket_parser (line 27) | typedef struct websocket_parser websocket_parser;
type websocket_parser_settings (line 28) | typedef struct websocket_parser_settings websocket_parser_settings;
type websocket_flags (line 30) | typedef enum websocket_flags {
type websocket_parser (line 50) | struct websocket_parser {
type websocket_parser_settings (line 64) | struct websocket_parser_settings {
FILE: http/wsdef.c
function ws_encode_key (line 11) | void ws_encode_key(const char* key, char accept[]) {
function ws_calc_frame_size (line 23) | int ws_calc_frame_size(int data_len, bool has_mask) {
function ws_build_frame (line 36) | int ws_build_frame(
FILE: http/wsdef.h
type ws_session_type (line 27) | enum ws_session_type {
type ws_opcode (line 32) | enum ws_opcode {
type ws_opcode (line 55) | enum ws_opcode
function HV_INLINE (line 58) | HV_INLINE int ws_client_build_frame(
function HV_INLINE (line 75) | HV_INLINE int ws_server_build_frame(
FILE: misc/grpc_server.h
function class (line 15) | class GrpcServer {
FILE: misc/win32_getopt.h
type option (line 119) | struct option
type option (line 121) | struct option
function _vwarnx (line 139) | static void
function warnx (line 148) | static void
function gcd (line 160) | static int
function permute_args (line 180) | static void
function getopt (line 219) | int
type option (line 268) | struct option /* specification for a long form option... */
function parse_long_options (line 288) | static int
function getopt_internal (line 416) | static int
function getopt_long (line 613) | int
function getopt_long_only (line 626) | int
FILE: mqtt/mqtt_client.c
function mqtt_next_mid (line 9) | static unsigned short mqtt_next_mid() {
function mqtt_client_send (line 14) | static int mqtt_client_send(mqtt_client_t* cli, const void* buf, int len) {
function mqtt_send_head (line 22) | static int mqtt_send_head(hio_t* io, int type, int length) {
function mqtt_send_head_with_mid (line 33) | static int mqtt_send_head_with_mid(hio_t* io, int type, unsigned short m...
function mqtt_send_ping (line 50) | static void mqtt_send_ping(hio_t* io) {
function mqtt_send_pong (line 60) | static void mqtt_send_pong(hio_t* io) {
function mqtt_send_disconnect (line 64) | static void mqtt_send_disconnect(hio_t* io) {
function mqtt_v5_skip_properties (line 70) | static int mqtt_v5_skip_properties(unsigned char** pp, unsigned char* en...
function mqtt_client_login (line 91) | static int mqtt_client_login(mqtt_client_t* cli) {
function connect_timeout_cb (line 202) | static void connect_timeout_cb(htimer_t* timer) {
function reconnect_timer_cb (line 217) | static void reconnect_timer_cb(htimer_t* timer) {
function mqtt_client_add_reconnect_timer (line 224) | static void mqtt_client_add_reconnect_timer(mqtt_client_t* cli) {
function on_close (line 232) | static void on_close(hio_t* io) {
function on_packet (line 243) | static void on_packet(hio_t* io, void* buf, int len) {
function on_connect (line 417) | static void on_connect(hio_t* io) {
function mqtt_client_t (line 443) | mqtt_client_t* mqtt_client_new(hloop_t* loop) {
function mqtt_client_free (line 458) | void mqtt_client_free(mqtt_client_t* cli) {
function mqtt_client_run (line 470) | void mqtt_client_run (mqtt_client_t* cli) {
function mqtt_client_stop (line 475) | void mqtt_client_stop(mqtt_client_t* cli) {
function mqtt_client_set_id (line 480) | void mqtt_client_set_id(mqtt_client_t* cli, const char* id) {
function mqtt_client_set_will (line 485) | void mqtt_client_set_will(mqtt_client_t* cli, mqtt_message_t* will) {
function mqtt_client_set_auth (line 493) | void mqtt_client_set_auth(mqtt_client_t* cli, const char* username, cons...
function mqtt_client_set_callback (line 503) | void mqtt_client_set_callback(mqtt_client_t* cli, mqtt_client_cb cb) {
function mqtt_client_set_userdata (line 508) | void mqtt_client_set_userdata(mqtt_client_t* cli, void* userdata) {
function mqtt_client_get_last_error (line 518) | int mqtt_client_get_last_error(mqtt_client_t* cli) {
function mqtt_client_set_ssl_ctx (line 523) | int mqtt_client_set_ssl_ctx(mqtt_client_t* cli, hssl_ctx_t ssl_ctx) {
function mqtt_client_new_ssl_ctx (line 528) | int mqtt_client_new_ssl_ctx(mqtt_client_t* cli, hssl_ctx_opt_t* opt) {
function mqtt_client_set_reconnect (line 536) | int mqtt_client_set_reconnect(mqtt_client_t* cli, reconn_setting_t* reco...
function mqtt_client_reconnect (line 548) | int mqtt_client_reconnect(mqtt_client_t* cli) {
function mqtt_client_set_connect_timeout (line 556) | void mqtt_client_set_connect_timeout(mqtt_client_t* cli, int ms) {
function mqtt_client_set_host (line 560) | void mqtt_client_set_host(mqtt_client_t* cli, const char* host, int port...
function mqtt_client_connect (line 566) | int mqtt_client_connect(mqtt_client_t* cli, const char* host, int port, ...
function mqtt_client_is_connected (line 590) | bool mqtt_client_is_connected(mqtt_client_t* cli) {
function mqtt_client_disconnect (line 594) | int mqtt_client_disconnect(mqtt_client_t* cli) {
function mqtt_client_publish (line 602) | int mqtt_client_publish(mqtt_client_t* cli, mqtt_message_t* msg) {
function mqtt_client_subscribe (line 654) | int mqtt_client_subscribe(mqtt_client_t* cli, const char* topic, int qos) {
function mqtt_client_unsubscribe (line 688) | int mqtt_client_unsubscribe(mqtt_client_t* cli, const char* topic) {
FILE: mqtt/mqtt_client.h
type mqtt_client_t (line 11) | typedef struct mqtt_client_s mqtt_client_t;
type mqtt_client_s (line 17) | struct mqtt_client_s {
function namespace (line 137) | namespace hv {
function reconnect (line 219) | int reconnect() {
function disconnect (line 223) | int disconnect() {
function isConnected (line 227) | bool isConnected() {
function invokeAckCallback (line 274) | void invokeAckCallback(int mid) {
function on_mqtt (line 286) | static void on_mqtt(mqtt_client_t* cli, int type) {
FILE: mqtt/mqtt_protocol.c
function mqtt_head_pack (line 4) | int mqtt_head_pack(mqtt_head_t* head, unsigned char buf[]) {
function mqtt_head_unpack (line 13) | int mqtt_head_unpack(mqtt_head_t* head, const unsigned char* buf, int le...
FILE: mqtt/mqtt_protocol.h
type mqtt_type_e (line 26) | typedef enum {
type mqtt_connack_e (line 44) | typedef enum {
type mqtt_head_t (line 53) | typedef struct mqtt_head_s {
type mqtt_message_t (line 61) | typedef struct mqtt_message_s {
function HV_INLINE (line 73) | HV_INLINE int mqtt_estimate_length(mqtt_head_t* head) {
FILE: protocol/dns.c
function dns_free (line 7) | void dns_free(dns_t* dns) {
function dns_name_encode (line 15) | int dns_name_encode(const char* domain, char* buf) {
function dns_name_decode (line 45) | int dns_name_decode(const char* buf, char* domain) {
function dns_rr_pack (line 68) | int dns_rr_pack(dns_rr_t* rr, char* buf, int len) {
function dns_rr_unpack (line 100) | int dns_rr_unpack(char* buf, int len, dns_rr_t* rr, int is_question) {
function dns_pack (line 142) | int dns_pa
Condensed preview — 371 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,254K chars).
[
{
"path": ".bazelrc",
"chars": 708,
"preview": "build --copt=-std=c99\nbuild --cxxopt=-std=c++11\nbuild --define BUILD_SHARED=ON\nbuild --define BUILD_STATIC=ON\nbuild --de"
},
{
"path": ".clang-format",
"chars": 2730,
"preview": "---\nLanguage: Cpp\n# BasedOnStyle: LLVM\nAccessModifierOffset: -4\nAlignAfterOpenBracket: Align\nAlignConsecutiveAss"
},
{
"path": ".gitattributes",
"chars": 35,
"preview": "cpputil/json.hpp linguist-vendored\n"
},
{
"path": ".github/workflows/CI.yml",
"chars": 2380,
"preview": "name: CI\n\non:\n push:\n paths-ignore:\n - '**.md'\n\n pull_request:\n paths-ignore:\n - '**.md'\n\njobs:\n buil"
},
{
"path": ".github/workflows/benchmark.yml",
"chars": 2355,
"preview": "name: benchmark\n\non:\n push:\n paths-ignore:\n - '**.md'\n\n pull_request:\n paths-ignore:\n - '**.md'\n\njobs:"
},
{
"path": ".gitignore",
"chars": 665,
"preview": "# Bazel\nbazel-*\nMODULE.bazel\nMODULE.bazel.lock\n\n# Compiled Object files\n*.o\n*.lo\n*.slo\n*.obj\n\n# Compiled Depfile\n*.d\n\n# "
},
{
"path": ".travis.yml",
"chars": 864,
"preview": "language: cpp\n\njobs:\n include:\n - os: linux\n dist: xenial\n compiler: gcc\n env: COVERALLS=no\n scr"
},
{
"path": "BUILD.bazel",
"chars": 10719,
"preview": "load(\"@rules_cc//cc:defs.bzl\", \"cc_binary\", \"cc_library\")\n\n\nconfig_setting(\n name = \"ios\",\n constraint_values = [\""
},
{
"path": "BUILD.md",
"chars": 2817,
"preview": "## Prequired\n\n- c99\n- c++11\n\ngcc4.8+, msvc2015 or later\n\n## Makefile\noptions see [config.ini](config.ini)\n```\n./configur"
},
{
"path": "CMakeLists.txt",
"chars": 10507,
"preview": "cmake_minimum_required(VERSION 3.6)\ncmake_policy(SET CMP0077 NEW)\n\nproject(hv VERSION 1.3.4)\n\noption(BUILD_SHARED \"build"
},
{
"path": "LICENSE",
"chars": 1508,
"preview": "BSD 3-Clause License\n\nCopyright (c) 2020, ithewei\nAll rights reserved.\n\nRedistribution and use in source and binary form"
},
{
"path": "Makefile",
"chars": 14081,
"preview": "include config.mk\ninclude Makefile.vars\n\nMAKEF=$(MAKE) -f Makefile.in\nALL_SRCDIRS=. base ssl event event/kcp util cpputi"
},
{
"path": "Makefile.in",
"chars": 7132,
"preview": "#+++++++++++++++++++++++++++++++++configure++++++++++++++++++++++++++++++++++++++++\n# OS=Windows,Linux,Android\n# ARCH=x8"
},
{
"path": "Makefile.vars",
"chars": 2113,
"preview": "MKDIR = -mkdir -p 2>/dev/null\nCP = -cp -r 2>/dev/null\nRM = -rm -r 2>/dev/null\nLDCONFIG = -ldconfig 2>/dev/null\n\nPREFIX ?"
},
{
"path": "README-CN.md",
"chars": 18409,
"preview": "[English](README.md) | 中文\n\n# libhv\n\n[](https://github."
},
{
"path": "README.md",
"chars": 14945,
"preview": "English | [中文](README-CN.md)\n\n# libhv\n\n[](https://gith"
},
{
"path": "TREE.md",
"chars": 899,
"preview": "## 目录结构\n\n```\n.\n├── base libhv基础设施,如常用宏定义、数据结构、日期时间、线程、进程、日志、套接字\n├── bin 可执行文件安装目录\n├── build cmake默认"
},
{
"path": "WORKSPACE.bazel",
"chars": 23,
"preview": "workspace(name = \"hv\")\n"
},
{
"path": "base/README.md",
"chars": 552,
"preview": "## 目录结构\n\n```\n.\n├── array.h 动态数组\n├── hatomic.h 原子操作\n├── hbase.h 基础函数\n├── hbuf.h 缓存\n├── hde"
},
{
"path": "base/array.h",
"chars": 3507,
"preview": "#ifndef HV_ARRAY_H_\n#define HV_ARRAY_H_\n\n/*\n * array\n * at: random access by pos\n * @effective\n * push_back,pop_back,del"
},
{
"path": "base/hatomic.h",
"chars": 3708,
"preview": "#ifndef HV_ATOMIC_H_\n#define HV_ATOMIC_H_\n\n#ifdef __cplusplus\n\n// c++11\n#include <atomic>\n\nusing std::atomic_flag;\nusing"
},
{
"path": "base/hbase.c",
"chars": 13280,
"preview": "#include \"hbase.h\"\n\n#ifdef OS_DARWIN\n#include <mach-o/dyld.h> // for _NSGetExecutablePath\n#endif\n\n#include \"hatomic.h\"\n\n"
},
{
"path": "base/hbase.h",
"chars": 4354,
"preview": "#ifndef HV_BASE_H_\n#define HV_BASE_H_\n\n#include \"hexport.h\"\n#include \"hplatform.h\" // for bool\n#include \"hdef.h\" // for "
},
{
"path": "base/hbuf.h",
"chars": 5426,
"preview": "#ifndef HV_BUF_H_\n#define HV_BUF_H_\n\n#include \"hdef.h\" // for MAX\n#include \"hbase.h\" // for HV_ALLOC, HV_FREE\n\ntypede"
},
{
"path": "base/hdef.h",
"chars": 4996,
"preview": "#ifndef HV_DEF_H_\n#define HV_DEF_H_\n\n#include \"hplatform.h\"\n\n#ifndef ABS\n#define ABS(n) ((n) > 0 ? (n) : -(n))\n#endif\n\n"
},
{
"path": "base/heap.h",
"chars": 4776,
"preview": "#ifndef HV_HEAP_H_\n#define HV_HEAP_H_\n\n#include <assert.h> // for assert\n#include <stddef.h> // for NULL\n\nstruct heap_no"
},
{
"path": "base/hendian.h",
"chars": 7350,
"preview": "#ifndef HV_ENDIAN_H_\n#define HV_ENDIAN_H_\n\n#include \"hplatform.h\"\n#if defined(OS_MAC)\n#include <libkern/OSByteOrder.h>\n#"
},
{
"path": "base/herr.c",
"chars": 358,
"preview": "#include \"herr.h\"\n\n#include <string.h> // for strerror\n\n// errcode => errmsg\nconst char* hv_strerror(int err) {\n if ("
},
{
"path": "base/herr.h",
"chars": 4532,
"preview": "#ifndef HV_ERR_H_\n#define HV_ERR_H_\n\n#include <errno.h>\n\n#include \"hexport.h\"\n\n#ifndef SYS_NERR\n#define SYS_NERR 133\n"
},
{
"path": "base/hlog.c",
"chars": 15378,
"preview": "#include \"hlog.h\"\n\n#include <assert.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <stdarg.h>\n#i"
},
{
"path": "base/hlog.h",
"chars": 7091,
"preview": "#ifndef HV_LOG_H_\n#define HV_LOG_H_\n\n/*\n * hlog is thread-safe\n */\n\n#include <string.h>\n\n#ifdef _WIN32\n#define DIR_SEPAR"
},
{
"path": "base/hmain.c",
"chars": 23911,
"preview": "#include \"hmain.h\"\n\n#include \"hbase.h\"\n#include \"hlog.h\"\n#include \"herr.h\"\n#include \"htime.h\"\n#include \"hthread.h\"\n\n#ifd"
},
{
"path": "base/hmain.h",
"chars": 3324,
"preview": "#ifndef HV_MAIN_H_\n#define HV_MAIN_H_\n\n#include \"hexport.h\"\n#include \"hplatform.h\"\n#include \"hdef.h\"\n#include \"hproc.h\"\n"
},
{
"path": "base/hmath.h",
"chars": 3404,
"preview": "#ifndef HV_MATH_H_\n#define HV_MATH_H_\n\n#include <math.h>\n\nstatic inline unsigned long floor2e(unsigned long num) {\n u"
},
{
"path": "base/hmutex.h",
"chars": 9240,
"preview": "#ifndef HV_MUTEX_H_\n#define HV_MUTEX_H_\n\n#include \"hexport.h\"\n#include \"hplatform.h\"\n#include \"htime.h\"\n\nBEGIN_EXTERN_C\n"
},
{
"path": "base/hplatform.h",
"chars": 9280,
"preview": "#ifndef HV_PLATFORM_H_\n#define HV_PLATFORM_H_\n\n#include \"hconfig.h\"\n\n// OS\n#if defined(WIN64) || defined(_WIN64)\n #de"
},
{
"path": "base/hproc.h",
"chars": 1621,
"preview": "#ifndef HV_PROC_H_\n#define HV_PROC_H_\n\n#include \"hplatform.h\"\n\ntypedef struct proc_ctx_s {\n pid_t pid; // t"
},
{
"path": "base/hsocket.c",
"chars": 12099,
"preview": "#include \"hsocket.h\"\n\n#include \"hdef.h\"\n#include \"htime.h\"\n\n#ifdef OS_UNIX\n#include <poll.h>\n#endif\n\n#ifdef OS_WIN\n#incl"
},
{
"path": "base/hsocket.h",
"chars": 8269,
"preview": "#ifndef HV_SOCKET_H_\n#define HV_SOCKET_H_\n\n#include \"hexport.h\"\n#include \"hplatform.h\"\n\n#ifdef ENABLE_UDS\n#ifdef OS_WIN\n"
},
{
"path": "base/hsysinfo.h",
"chars": 1773,
"preview": "#ifndef HV_SYS_INFO_H_\n#define HV_SYS_INFO_H_\n\n#include \"hplatform.h\"\n\n#ifdef OS_LINUX\n#include <sys/sysinfo.h>\n#endif\n\n"
},
{
"path": "base/hthread.h",
"chars": 5041,
"preview": "#ifndef HV_THREAD_H_\n#define HV_THREAD_H_\n\n#include \"hplatform.h\"\n\n#ifdef OS_WIN\n#define hv_getpid (long)GetCurrentPro"
},
{
"path": "base/htime.c",
"chars": 7057,
"preview": "#include \"htime.h\"\n\nstatic const char* s_weekdays[] = {\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\","
},
{
"path": "base/htime.h",
"chars": 3286,
"preview": "#ifndef HV_TIME_H_\n#define HV_TIME_H_\n\n#include \"hexport.h\"\n#include \"hplatform.h\"\n\nBEGIN_EXTERN_C\n\n#define SECONDS_PER_"
},
{
"path": "base/hversion.c",
"chars": 986,
"preview": "#include \"hversion.h\"\n\n#include \"htime.h\"\n\nconst char* hv_compile_version() {\n static char s_version[16] = {0};\n d"
},
{
"path": "base/hversion.h",
"chars": 774,
"preview": "#ifndef HV_VERSION_H_\n#define HV_VERSION_H_\n\n#include \"hexport.h\"\n#include \"hdef.h\"\n\nBEGIN_EXTERN_C\n\n#define HV_VERSION_"
},
{
"path": "base/list.h",
"chars": 21681,
"preview": "#ifndef _LINUX_LIST_H\n#define _LINUX_LIST_H\n\n/*\n * Simple doubly linked list implementation.\n *\n * Some of the internal "
},
{
"path": "base/netinet.h",
"chars": 5426,
"preview": "#ifndef HV_NETINET_H_\n#define HV_NETINET_H_\n\n#include \"hplatform.h\"\n\n/*\n#ifdef OS_UNIX\n#include <netinet/in.h>\n#include "
},
{
"path": "base/queue.h",
"chars": 2534,
"preview": "#ifndef HV_QUEUE_H_\n#define HV_QUEUE_H_\n\n/*\n * queue\n * FIFO: push_back,pop_front\n * stack\n * LIFO: push_back,pop_back\n "
},
{
"path": "base/rbtree.c",
"chars": 11179,
"preview": "/*\n Red Black Trees\n (C) 1999 Andrea Arcangeli <andrea@suse.de>\n (C) 2002 David Woodhouse <dwmw2@infradead.org>\n\n "
},
{
"path": "base/rbtree.h",
"chars": 4442,
"preview": "/*\n Red Black Trees\n (C) 1999 Andrea Arcangeli <andrea@suse.de>\n\n This program is free software; you can redistribut"
},
{
"path": "cert/cacert.pem",
"chars": 224081,
"preview": "##\n## Bundle of CA Root Certificates\n##\n## Certificate data from Mozilla as of: Wed Aug 28 03:12:10 2019 GMT\n##\n## This "
},
{
"path": "cert/gen.sh",
"chars": 102,
"preview": "openssl genrsa -out server.key 2048\nopenssl req -new -x509 -key server.key -out server.crt -days 3650\n"
},
{
"path": "cert/server.crt",
"chars": 1277,
"preview": "-----BEGIN CERTIFICATE-----\nMIIDgjCCAmqgAwIBAgIJAL/XKTs4cCwRMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV\nBAYTAkNOMREwDwYDVQQIDAhTaGF"
},
{
"path": "cert/server.key",
"chars": 1679,
"preview": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEA0knkNpmugSA3fgfoDe6rmoNGUl78QuFZya2SPntxhvlT9Pf0\nLt0SOoZ+FRFv80S5htigRv7"
},
{
"path": "cmake/ios.toolchain.cmake",
"chars": 47101,
"preview": "# This file is part of the ios-cmake project. It was retrieved from\n# https://github.com/leetal/ios-cmake.git, which is "
},
{
"path": "cmake/libhvConfig.cmake",
"chars": 3106,
"preview": "\ninclude(SelectLibraryConfigurations)\n\nfind_path(libhv_INCLUDE_DIRS hv/hv.h)\nmessage(\"libhv_INCLUDE_DIRS: \" ${libhv_INCL"
},
{
"path": "cmake/utils.cmake",
"chars": 1080,
"preview": "include(CheckIncludeFiles)\nmacro(check_header header)\n string(TOUPPER ${header} str1)\n string(REGEX REPLACE \"[/.]\""
},
{
"path": "cmake/vars.cmake",
"chars": 1913,
"preview": "# see Makefile.vars\n\nset(BASE_HEADERS\n base/hplatform.h\n base/hdef.h\n base/hatomic.h\n base/herr.h\n base/h"
},
{
"path": "config.ini",
"chars": 741,
"preview": "# Don't modify this file, you should modify config.mk or\n# run ./configure --with-MODULE --enable-FEATURE\n\nPREFIX=/usr/l"
},
{
"path": "configure",
"chars": 7306,
"preview": "#!/bin/bash\n\n. \"$(dirname \"$0\")/scripts/shini.sh\"\n\nprint_help() {\n shini_parse \"config.ini\"\n cat << END\nUsage: ./c"
},
{
"path": "cpputil/LRUCache.h",
"chars": 8795,
"preview": "#ifndef HV_LRU_CACHE_H_\n#define HV_LRU_CACHE_H_\n\n#include <unordered_map>\n#include <list>\n#include <mutex>\n#include <mem"
},
{
"path": "cpputil/RAII.cpp",
"chars": 1819,
"preview": "#include \"hplatform.h\"\n\n#ifdef OS_WIN\n#ifdef ENABLE_WINDUMP\n#include <dbghelp.h>\n#ifdef _MSC_VER\n#pragma comment(lib,\"db"
},
{
"path": "cpputil/README.md",
"chars": 406,
"preview": "## 目录结构\n\n```\n.\n├── hasync.h hv::async实现\n├── hdir.h 目录(ls实现)\n├── hfile.h 文件类\n├── hobjectpool.h "
},
{
"path": "cpputil/ThreadLocalStorage.cpp",
"chars": 662,
"preview": "#include \"ThreadLocalStorage.h\"\n\n#include \"hthread.h\"\n\nnamespace hv {\n\nThreadLocalStorage ThreadLocalStorage::tls[Thread"
},
{
"path": "cpputil/ThreadLocalStorage.h",
"chars": 1496,
"preview": "#ifndef HV_THREAD_LOCAL_STORAGE_H_\n#define HV_THREAD_LOCAL_STORAGE_H_\n\n#include \"hexport.h\"\n#include \"hplatform.h\"\n\n#ifd"
},
{
"path": "cpputil/hasync.cpp",
"chars": 73,
"preview": "#include \"hasync.h\"\n\nnamespace hv {\n\nSINGLETON_IMPL(GlobalThreadPool)\n\n}\n"
},
{
"path": "cpputil/hasync.h",
"chars": 1341,
"preview": "#ifndef HV_ASYNC_H_\n#define HV_ASYNC_H_\n\n#include \"hexport.h\"\n#include \"hthreadpool.h\"\n#include \"singleton.h\"\n\nnamespace"
},
{
"path": "cpputil/hdir.cpp",
"chars": 2921,
"preview": "#include \"hdir.h\"\n\n#include \"hplatform.h\"\n\n#ifdef OS_WIN\n#include \"hstring.h\" // import hv::utf8_to_wchar hv::wchar_to_u"
},
{
"path": "cpputil/hdir.h",
"chars": 1832,
"preview": "#ifndef HV_DIR_H_\n#define HV_DIR_H_\n\n/*\n *@code\nint main(int argc, char* argv[]) {\n const char* dir = \".\";\n if (ar"
},
{
"path": "cpputil/hfile.h",
"chars": 2949,
"preview": "#ifndef HV_FILE_H_\n#define HV_FILE_H_\n\n#include <string> // for std::string\n\n#include \"hplatform.h\" // for stat\n#include"
},
{
"path": "cpputil/hmap.h",
"chars": 1401,
"preview": "#ifndef HV_MAP_H_\n#define HV_MAP_H_\n\n#include \"hconfig.h\"\n\n#include <map>\n#include <string>\n\n// MultiMap\nnamespace std {"
},
{
"path": "cpputil/hobjectpool.h",
"chars": 4375,
"preview": "#ifndef HV_OBJECT_POOL_H_\n#define HV_OBJECT_POOL_H_\n\n/*\n * @usage unittest/objectpool_test.cpp\n */\n\n#include <list>\n#inc"
},
{
"path": "cpputil/hpath.cpp",
"chars": 2831,
"preview": "#include \"hpath.h\"\n\n#include \"hplatform.h\"\n\nbool HPath::exists(const char* path) {\n return access(path, 0) == 0;\n}\n\nb"
},
{
"path": "cpputil/hpath.h",
"chars": 809,
"preview": "#ifndef HV_PATH_H_\n#define HV_PATH_H_\n\n#include <string> // for std::string\n\n#include \"hexport.h\"\n\nclass HV_EXPORT HPath"
},
{
"path": "cpputil/hscope.h",
"chars": 1441,
"preview": "#ifndef HV_SCOPE_H_\n#define HV_SCOPE_H_\n\n#include <functional>\ntypedef std::function<void()> Function;\n\n#include \"hdef.h"
},
{
"path": "cpputil/hstring.cpp",
"chars": 6575,
"preview": "#include \"hstring.h\"\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <stdarg.h>\n\nnamespace hv {\n\nst"
},
{
"path": "cpputil/hstring.h",
"chars": 3652,
"preview": "#ifndef HV_STRING_H_\n#define HV_STRING_H_\n\n#include <string>\n#include <vector>\n\n#include <iostream>\n#include <sstream>\n\n"
},
{
"path": "cpputil/hthreadpool.h",
"chars": 6907,
"preview": "#ifndef HV_THREAD_POOL_H_\n#define HV_THREAD_POOL_H_\n\n/*\n * @usage unittest/threadpool_test.cpp\n */\n\n#include <time.h>\n#i"
},
{
"path": "cpputil/hurl.cpp",
"chars": 5225,
"preview": "#include \"hurl.h\"\n\n#include \"hdef.h\"\n#include \"hbase.h\"\n\n/*\nstatic bool Curl_isunreserved(unsigned char in)\n{\n switch"
},
{
"path": "cpputil/hurl.h",
"chars": 847,
"preview": "#ifndef HV_URL_H_\n#define HV_URL_H_\n\n#include <string> // import std::string\n\n#include \"hexport.h\"\n\nclass HV_EXPORT HUrl"
},
{
"path": "cpputil/ifconfig.cpp",
"chars": 7260,
"preview": "#include \"ifconfig.h\"\n\n#include \"hplatform.h\"\n\n#ifdef OS_LINUX\n#include <unistd.h>\n#include <sys/types.h>\n#include <sys/"
},
{
"path": "cpputil/ifconfig.h",
"chars": 718,
"preview": "#ifndef HV_IFCONFIG_H_\n#define HV_IFCONFIG_H_\n\n#include <vector>\n\n#include \"hexport.h\"\n\n#ifdef _MSC_VER\n#pragma comment("
},
{
"path": "cpputil/iniparser.cpp",
"chars": 9918,
"preview": "#include \"iniparser.h\"\n\n#include <sstream>\n\n#include \"hdef.h\"\n#include \"herr.h\"\n#include \"hstring.h\"\n#include \"hfile.h\"\n"
},
{
"path": "cpputil/iniparser.h",
"chars": 1272,
"preview": "#ifndef HV_INI_PARSER_H_\n#define HV_INI_PARSER_H_\n\n#include <string>\n#include <list>\n\n#include \"hexport.h\"\n\n#define DEFA"
},
{
"path": "cpputil/json.hpp",
"chars": 953435,
"preview": "// __ _____ _____ _____\n// __| | __| | | | JSON for Modern C++\n// | | |__ | | | | | | version 3.12"
},
{
"path": "cpputil/singleton.h",
"chars": 978,
"preview": "#ifndef HV_SINGLETON_H_\n#define HV_SINGLETON_H_\n\n#include <mutex>\n\n#define DISABLE_COPY(Class) \\\n Class(const Class&)"
},
{
"path": "docs/API.md",
"chars": 10401,
"preview": "# libhv API Manual\n\n## base\n\n### hplatform.h\n- OS: OS_WIN, OS_UNIX (OS_LINUX, OS_ANDROID, OS_DARWIN ...)\n- ARCH: ARCH_X8"
},
{
"path": "docs/PLAN.md",
"chars": 571,
"preview": "## Done\n\n- base: cross platfrom infrastructure\n- event: select/poll/epoll/wepoll/kqueue/port/io_uring\n- ssl: openssl/gnu"
},
{
"path": "docs/cn/Channel.md",
"chars": 3331,
"preview": "通道类\n\n```c++\n\nclass Channel {\n\n // 返回底层的io结构体指针\n hio_t* io() { return io_; }\n\n // 返回socket文件描述符\n int "
},
{
"path": "docs/cn/EventLoop.md",
"chars": 2347,
"preview": "事件循环类\n\n```c++\n\nclass EventLoop {\n\n // 返回底层的loop结构体指针\n hloop_t* loop();\n\n // 运行\n void run();\n // 停止\n vo"
},
{
"path": "docs/cn/HttpClient.md",
"chars": 2638,
"preview": "HTTP 客户端类\n\n```c++\n\nclass HttpClient {\n\n // 设置超时\n int setTimeout(int timeout);\n\n // 设置SSL/TLS\n int setSslCtx("
},
{
"path": "docs/cn/HttpContext.md",
"chars": 2380,
"preview": "```c++\n\nclass HttpContext {\n\n /* 获取请求信息 */\n // 获取客户端IP\n std::string ip();\n // 获取客户端端口\n int port();\n //"
},
{
"path": "docs/cn/HttpMessage.md",
"chars": 3203,
"preview": "```c++\n\nclass HttpMessage {\n // 设置/获取头部\n void SetHeader(const char* key, const std::string& value);\n std::strin"
},
{
"path": "docs/cn/HttpServer.md",
"chars": 3748,
"preview": "HTTP 服务端类\n\n```c++\n\n// HTTP服务类\nclass HttpServer {\n\n // 注册HTTP业务类\n void registerHttpService(HttpService* service);\n\n"
},
{
"path": "docs/cn/README.md",
"chars": 556,
"preview": "## c接口\n\n- [hloop: 事件循环](hloop.md)\n- [hbase: 基础函数](hbase.md)\n- [hlog: 日志](hlog.md)\n\n## c++接口\n\n- [class EventLoop: 事件循环类]"
},
{
"path": "docs/cn/TcpClient.md",
"chars": 1289,
"preview": "TCP 客户端类\n\n```c++\n\nclass TcpClient {\n\n // 返回所在的事件循环\n const EventLoopPtr& loop();\n\n // 创建套接字\n int createsocket"
},
{
"path": "docs/cn/TcpServer.md",
"chars": 1208,
"preview": "TCP 服务端类\n\n```c++\n\nclass TcpServer {\n\n // 返回索引的事件循环\n EventLoopPtr loop(int idx = -1);\n\n // 创建套接字\n int creates"
},
{
"path": "docs/cn/UdpClient.md",
"chars": 948,
"preview": "UDP 客户端类\n\n```c++\n\nclass UdpClient {\n\n // 返回所在的事件循环\n const EventLoopPtr& loop();\n\n // 创建套接字\n int createsocket"
},
{
"path": "docs/cn/UdpServer.md",
"chars": 853,
"preview": "UDP 服务端类\n\n```c++\n\nclass UdpServer {\n\n // 返回所在的事件循环\n const EventLoopPtr& loop();\n\n // 创建套接字\n int createsocket"
},
{
"path": "docs/cn/WebSocketClient.md",
"chars": 764,
"preview": "WebSocket 客户端类\n\n```c++\n\nclass WebSocketClient {\n\n // 打开回调\n std::function<void()> onopen;\n // 关闭回调\n std::func"
},
{
"path": "docs/cn/WebSocketServer.md",
"chars": 658,
"preview": "WebSocket 服务端类\n\n```c++\n\n// WebSocketServer 继承自 HttpServer\nclass WebSocketServer : public HttpServer {\n\n // 注册WebSocke"
},
{
"path": "docs/cn/hbase.md",
"chars": 2269,
"preview": "一些基础函数\n\n```c\n\n/* hv内存分配/释放函数 */\nvoid* hv_malloc(size_t size);\nvoid* hv_realloc(void* oldptr, size_t newsize, size_t olds"
},
{
"path": "docs/cn/hlog.md",
"chars": 3844,
"preview": "日志\n\n```c\n\n// 标准输出日志\nvoid stdout_logger(int loglevel, const char* buf, int len);\n\n// 标准错误日志\nvoid stderr_logger(int loglev"
},
{
"path": "docs/cn/hloop.md",
"chars": 20093,
"preview": "事件循环和IO多路复用机制介绍\n\n事件循环是`libevent、libev、libuv、libhv`这类网络库里最核心的概念,即在事件循环里处理IO读写事件、定时器事件、自定义事件等各种事件;<br>\nIO多路复用即在一个IO线程监听多个f"
},
{
"path": "echo-servers/asio_echo.cpp",
"chars": 3040,
"preview": "//\n// async_tcp_echo_server.cpp\n// ~~~~~~~~~~~~~~~~~~~~~~~~~\n//\n// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chri"
},
{
"path": "echo-servers/benchmark.sh",
"chars": 1807,
"preview": "#!/bin/bash\n\nhost=127.0.0.1\nport=2000\nconnections=100\nduration=10\nthreads=2\nsendbytes=1024\n\nwhile getopts 'h:p:c:d:t:' o"
},
{
"path": "echo-servers/build.sh",
"chars": 990,
"preview": "#!/bin/bash\n\nSCRIPT_DIR=$(cd `dirname $0`; pwd)\nROOT_DIR=${SCRIPT_DIR}/..\n\n# install libevent libev libuv asio poco\nUNAM"
},
{
"path": "echo-servers/libev_echo.c",
"chars": 1815,
"preview": "#include <unistd.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include <sys/types.h>\n#include <sys/soc"
},
{
"path": "echo-servers/libevent_echo.c",
"chars": 1809,
"preview": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"event2/event.h\"\n#include \"event2/listener.h\"\n#incl"
},
{
"path": "echo-servers/libhv_echo.c",
"chars": 637,
"preview": "#include \"hv/hloop.h\"\n\nvoid on_close(hio_t* io) {\n}\n\nvoid on_recv(hio_t* io, void* buf, int readbytes) {\n hio_write(i"
},
{
"path": "echo-servers/libuv_echo.c",
"chars": 1853,
"preview": "#define _GNU_SOURCE 1\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"uv.h\"\n\ntypedef struct {\n "
},
{
"path": "echo-servers/muduo_echo.cpp",
"chars": 1454,
"preview": "// @see muduo/examples/simple/echo\n#include \"muduo/base/Logging.h\"\n#include \"muduo/net/EventLoop.h\"\n#include \"muduo/net/"
},
{
"path": "echo-servers/pingpong_client.cpp",
"chars": 3973,
"preview": "#include \"hv/hmain.h\" // import parse_opt\n#include \"hv/hloop.h\"\n#include \"hv/hsocket.h\"\n\n#include \"hv/EventLoopThreadPoo"
},
{
"path": "echo-servers/poco_echo.cpp",
"chars": 7301,
"preview": "//\n// EchoServer.cpp\n//\n// $Id: //poco/1.3/Net/samples/EchoServer/src/EchoServer.cpp#1 $\n//\n// This sample demonstrates "
},
{
"path": "etc/hmain_test.conf",
"chars": 247,
"preview": "# [root]\n\n# logfile = logs/test.log\n# loglevel = [VERBOSE,DEBUG,INFO,WARN,ERROR,FATAL,SILENT]\nloglevel = DEBUG\nlog_remai"
},
{
"path": "etc/httpd.conf",
"chars": 1171,
"preview": "# [root]\n\n# logfile = logs/httpd.log\n# loglevel = [VERBOSE,DEBUG,INFO,WARN,ERROR,FATAL,SILENT]\nloglevel = INFO\nlog_remai"
},
{
"path": "etc/nginx.conf",
"chars": 694,
"preview": "# cd libhv\n# sudo nginx -p . -c etc/nginx.conf\n# bin/httpd -c etc/httpd.conf -s restart -d\n# bin/curl -v http://127.0.0."
},
{
"path": "event/README.md",
"chars": 514,
"preview": "## 目录结构\n\n```\n.\n├── hloop.h 事件循环模块对外头文件\n├── hevent.h 事件结构体定义\n├── nlog.h 网络日志\n├── unpack.h 拆包\n├── rudp.h "
},
{
"path": "event/epoll.c",
"chars": 3924,
"preview": "#include \"iowatcher.h\"\n\n#ifdef EVENT_EPOLL\n#include \"hplatform.h\"\n#include \"hdef.h\"\n#include \"hevent.h\"\n\n#ifdef OS_WIN\n#"
},
{
"path": "event/evport.c",
"chars": 3895,
"preview": "#include \"iowatcher.h\"\n\n#ifdef EVENT_PORT\n\n#include \"hplatform.h\"\n#include \"hdef.h\"\n#include \"hevent.h\"\n\n#include <port."
},
{
"path": "event/hevent.c",
"chars": 26613,
"preview": "#include \"hevent.h\"\n#include \"hsocket.h\"\n#include \"hatomic.h\"\n#include \"hlog.h\"\n#include \"herr.h\"\n\n#include \"unpack.h\"\n\n"
},
{
"path": "event/hevent.h",
"chars": 8506,
"preview": "#ifndef HV_EVENT_H_\n#define HV_EVENT_H_\n\n#include \"hloop.h\"\n#include \"iowatcher.h\"\n#include \"rudp.h\"\n\n#include \"hbuf.h\"\n"
},
{
"path": "event/hloop.c",
"chars": 31917,
"preview": "#include \"hloop.h\"\n#include \"hevent.h\"\n#include \"iowatcher.h\"\n\n#include \"hdef.h\"\n#include \"hbase.h\"\n#include \"hlog.h\"\n#i"
},
{
"path": "event/hloop.h",
"chars": 28344,
"preview": "#ifndef HV_LOOP_H_\n#define HV_LOOP_H_\n\n#include \"hexport.h\"\n#include \"hplatform.h\"\n#include \"hdef.h\"\n#include \"hssl.h\"\n\n"
},
{
"path": "event/io_uring.c",
"chars": 6290,
"preview": "#include \"iowatcher.h\"\n\n#ifdef EVENT_IO_URING\n#include \"hplatform.h\"\n#include \"hdef.h\"\n#include \"hevent.h\"\n\n#include <li"
},
{
"path": "event/iocp.c",
"chars": 2238,
"preview": "#include \"iowatcher.h\"\n\n#ifdef EVENT_IOCP\n#include \"hplatform.h\"\n#include \"hdef.h\"\n\n#include \"hevent.h\"\n#include \"overla"
},
{
"path": "event/iowatcher.h",
"chars": 1021,
"preview": "#ifndef IO_WATCHER_H_\n#define IO_WATCHER_H_\n\n#include \"hloop.h\"\n\n#include \"hplatform.h\"\n#if !defined(EVENT_SELECT) && "
},
{
"path": "event/kcp/LICENSE",
"chars": 1090,
"preview": "MIT License\n\nCopyright (c) 2017 Lin Wei (skywind3000 at gmail.com)\n\nPermission is hereby granted, free of charge, to any"
},
{
"path": "event/kcp/hkcp.c",
"chars": 5423,
"preview": "#include \"hkcp.h\"\n\n#if WITH_KCP\n\n#include \"hevent.h\"\n#include \"hlog.h\"\n#include \"hthread.h\"\n\nstatic kcp_setting_t s_kcp_"
},
{
"path": "event/kcp/hkcp.h",
"chars": 681,
"preview": "#ifndef HV_KCP_H_\n#define HV_KCP_H_\n\n#include \"hloop.h\"\n\n#if WITH_KCP\n\n#include \"ikcp.h\"\n#include \"hbuf.h\"\n\n#define DEFA"
},
{
"path": "event/kcp/ikcp.c",
"chars": 32997,
"preview": "//=====================================================================\r\n//\r\n// KCP - A Better ARQ Protocol Implementati"
},
{
"path": "event/kcp/ikcp.h",
"chars": 12582,
"preview": "//=====================================================================\r\n//\r\n// KCP - A Better ARQ Protocol Implementati"
},
{
"path": "event/kqueue.c",
"chars": 5374,
"preview": "#include \"iowatcher.h\"\n\n#ifdef EVENT_KQUEUE\n#include \"hplatform.h\"\n#include \"hdef.h\"\n\n#include <sys/event.h>\n\n#include \""
},
{
"path": "event/nio.c",
"chars": 18686,
"preview": "#include \"iowatcher.h\"\n#ifndef EVENT_IOCP\n#include \"hevent.h\"\n#include \"hsocket.h\"\n#include \"hssl.h\"\n#include \"hlog.h\"\n#"
},
{
"path": "event/nlog.c",
"chars": 2246,
"preview": "#include \"nlog.h\"\n\n#include \"list.h\"\n#include \"hdef.h\"\n#include \"hbase.h\"\n#include \"hsocket.h\"\n#include \"hmutex.h\"\n\ntype"
},
{
"path": "event/nlog.h",
"chars": 814,
"preview": "#ifndef HV_NLOG_H_\n#define HV_NLOG_H_\n\n// nlog: extend hlog use hloop\n\n/* you can recv log by:\n * Windows: telnet ip por"
},
{
"path": "event/noevent.c",
"chars": 413,
"preview": "#include \"iowatcher.h\"\n\n#ifdef EVENT_NOEVENT\nint iowatcher_init(hloop_t* loop) {\n return 0;\n}\n\nint iowatcher_cleanup("
},
{
"path": "event/overlapio.c",
"chars": 13306,
"preview": "// WARN: overlapio maybe need MemoryPool to avoid alloc/free\n#include \"iowatcher.h\"\n\n#ifdef EVENT_IOCP\n#include \"overlap"
},
{
"path": "event/overlapio.h",
"chars": 629,
"preview": "#ifndef HV_OVERLAPPED_H_\n#define HV_OVERLAPPED_H_\n\n#include \"iowatcher.h\"\n\n#ifdef EVENT_IOCP\n\n#include \"hbuf.h\"\n#include"
},
{
"path": "event/poll.c",
"chars": 3565,
"preview": "#include \"iowatcher.h\"\n\n#ifdef EVENT_POLL\n#include \"hplatform.h\"\n#include \"hdef.h\"\n#include \"hevent.h\"\n\n#ifdef OS_WIN\n#d"
},
{
"path": "event/rudp.c",
"chars": 4465,
"preview": "#include \"rudp.h\"\n\n#if WITH_RUDP\n\n#include \"hevent.h\"\n#include \"hsocket.h\"\n\nvoid rudp_entry_free(rudp_entry_t* entry) {\n"
},
{
"path": "event/rudp.h",
"chars": 1225,
"preview": "#ifndef HV_RUDP_H_\n#define HV_RUDP_H_\n\n#include \"hloop.h\"\n\n#if WITH_RUDP\n\n#include \"rbtree.h\"\n#include \"hsocket.h\"\n#incl"
},
{
"path": "event/select.c",
"chars": 4513,
"preview": "#include \"iowatcher.h\"\n\n#ifdef EVENT_SELECT\n#include \"hplatform.h\"\n#include \"hdef.h\"\n#include \"hevent.h\"\n#include \"hsock"
},
{
"path": "event/unpack.c",
"chars": 6488,
"preview": "#include \"unpack.h\"\n#include \"hevent.h\"\n#include \"herr.h\"\n#include \"hlog.h\"\n#include \"hmath.h\"\n\nint hio_unpack(hio_t* io"
},
{
"path": "event/unpack.h",
"chars": 344,
"preview": "#ifndef HV_UNPACK_H_\n#define HV_UNPACK_H_\n\n#include \"hloop.h\"\n\nint hio_unpack(hio_t* io, void* buf, int readbytes);\nint "
},
{
"path": "event/wepoll/LICENSE",
"chars": 1394,
"preview": "wepoll - epoll for Windows\nhttps://github.com/piscisaureus/wepoll\n\nCopyright 2012-2020, Bert Belder <bertbelder@gmail.co"
},
{
"path": "event/wepoll/README.md",
"chars": 7940,
"preview": "# wepoll - epoll for windows\n\n[![][ci status badge]][ci status link]\n\nThis library implements the [epoll][man epoll] API"
},
{
"path": "event/wepoll/wepoll.c",
"chars": 69998,
"preview": "/*\n * wepoll - epoll for Windows\n * https://github.com/piscisaureus/wepoll\n *\n * Copyright 2012-2020, Bert Belder <bertb"
},
{
"path": "event/wepoll/wepoll.h",
"chars": 3471,
"preview": "/*\n * wepoll - epoll for Windows\n * https://github.com/piscisaureus/wepoll\n *\n * Copyright 2012-2020, Bert Belder <bertb"
},
{
"path": "evpp/Buffer.h",
"chars": 198,
"preview": "#ifndef HV_BUFFER_HPP_\n#define HV_BUFFER_HPP_\n\n#include <memory>\n\n#include \"hbuf.h\"\n\nnamespace hv {\n\ntypedef HBuf Buffer"
},
{
"path": "evpp/Channel.h",
"chars": 10102,
"preview": "#ifndef HV_CHANNEL_HPP_\n#define HV_CHANNEL_HPP_\n\n#include <string>\n#include <functional>\n#include <memory>\n#include <ato"
},
{
"path": "evpp/Event.h",
"chars": 937,
"preview": "#ifndef HV_EVENT_HPP_\n#define HV_EVENT_HPP_\n\n#include <functional>\n#include <memory>\n\n#include \"hloop.h\"\n\nnamespace hv {"
},
{
"path": "evpp/EventLoop.h",
"chars": 7633,
"preview": "#ifndef HV_EVENT_LOOP_HPP_\n#define HV_EVENT_LOOP_HPP_\n\n#include <functional>\n#include <queue>\n#include <map>\n#include <m"
},
{
"path": "evpp/EventLoopThread.h",
"chars": 2907,
"preview": "#ifndef HV_EVENT_LOOP_THREAD_HPP_\n#define HV_EVENT_LOOP_THREAD_HPP_\n\n#include <thread>\n\n#include \"hlog.h\"\n\n#include \"Eve"
},
{
"path": "evpp/EventLoopThreadPool.h",
"chars": 4317,
"preview": "#ifndef HV_EVENT_LOOP_THREAD_POOL_HPP_\n#define HV_EVENT_LOOP_THREAD_POOL_HPP_\n\n#include \"EventLoopThread.h\"\n#include \"hb"
},
{
"path": "evpp/EventLoopThreadPool_test.cpp",
"chars": 1292,
"preview": "/*\n * EventLoopThreadPool_test.cpp\n *\n * @build: make evpp\n *\n */\n\n#include \"hv.h\"\n\n#include \"EventLoopThreadPool.h\"\n\nus"
},
{
"path": "evpp/EventLoopThread_test.cpp",
"chars": 957,
"preview": "/*\n * EventLoopThread_test.cpp\n *\n * @build: make evpp\n *\n */\n\n#include \"hv.h\"\n\n#include \"EventLoopThread.h\"\n\nusing name"
},
{
"path": "evpp/EventLoop_test.cpp",
"chars": 876,
"preview": "/*\n * EventLoop_test.cpp\n *\n * @build: make evpp\n *\n */\n\n#include \"hv.h\"\n\n#include \"EventLoop.h\"\n\nusing namespace hv;\n\ns"
},
{
"path": "evpp/README.md",
"chars": 762,
"preview": "The evpp module is designed to be header-only and does not participate in compilation.\nhloop.h is encapsulated into c++ "
},
{
"path": "evpp/Status.h",
"chars": 914,
"preview": "#ifndef HV_STATUS_HPP_\n#define HV_STATUS_HPP_\n\n#include <atomic>\n\nnamespace hv {\n\nclass Status {\npublic:\n enum KStatu"
},
{
"path": "evpp/TcpClient.h",
"chars": 9256,
"preview": "#ifndef HV_TCP_CLIENT_HPP_\n#define HV_TCP_CLIENT_HPP_\n\n#include \"hsocket.h\"\n#include \"hssl.h\"\n#include \"hlog.h\"\n\n#includ"
},
{
"path": "evpp/TcpClientEventLoop_test.cpp",
"chars": 3750,
"preview": "/*\n * TcpClientEventLoop_test.cpp\n *\n * @build make evpp\n * @server bin/TcpServer_test 1234\n * @client bin/TcpClient"
},
{
"path": "evpp/TcpClient_test.cpp",
"chars": 2642,
"preview": "/*\n * TcpClient_test.cpp\n *\n * @build make evpp\n * @server bin/TcpServer_test 1234\n * @client bin/TcpClient_test 123"
},
{
"path": "evpp/TcpServer.h",
"chars": 9906,
"preview": "#ifndef HV_TCP_SERVER_HPP_\n#define HV_TCP_SERVER_HPP_\n\n#include \"hsocket.h\"\n#include \"hssl.h\"\n#include \"hlog.h\"\n\n#includ"
},
{
"path": "evpp/TcpServer_test.cpp",
"chars": 1959,
"preview": "/*\n * TcpServer_test.cpp\n *\n * @build make evpp\n * @server bin/TcpServer_test 1234\n * @client bin/TcpClient_test 123"
},
{
"path": "evpp/TimerThread.h",
"chars": 1175,
"preview": "#ifndef HV_TIMER_THREAD_HPP_\n#define HV_TIMER_THREAD_HPP_\n\n#include \"EventLoopThread.h\"\n\nnamespace hv {\n\nclass TimerThre"
},
{
"path": "evpp/TimerThread_test.cpp",
"chars": 1419,
"preview": "/*\n * TimerThread_test.cpp\n *\n * @build: make evpp\n *\n */\n\n#include \"TimerThread.h\"\n#include \"singleton.h\"\n\nnamespace hv"
},
{
"path": "evpp/UdpClient.h",
"chars": 5588,
"preview": "#ifndef HV_UDP_CLIENT_HPP_\n#define HV_UDP_CLIENT_HPP_\n\n#include \"hsocket.h\"\n\n#include \"EventLoopThread.h\"\n#include \"Chan"
},
{
"path": "evpp/UdpClient_test.cpp",
"chars": 1449,
"preview": "/*\n * UdpClient_test.cpp\n *\n * @build make evpp\n * @server bin/UdpServer_test 1234\n * @client bin/UdpClient_test 123"
},
{
"path": "evpp/UdpServer.h",
"chars": 4620,
"preview": "#ifndef HV_UDP_SERVER_HPP_\n#define HV_UDP_SERVER_HPP_\n\n#include \"hsocket.h\"\n\n#include \"EventLoopThreadPool.h\"\n#include \""
},
{
"path": "evpp/UdpServer_test.cpp",
"chars": 1081,
"preview": "/*\n * UdpServer_test.cpp\n *\n * @build make evpp\n * @server bin/UdpServer_test 1234\n * @client bin/UdpClient_test 123"
},
{
"path": "evpp/build_test.sh",
"chars": 100,
"preview": "#!/bin/bash\n\nSCRIPT_DIR=$(cd `dirname $0`; pwd)\nROOT_DIR=${SCRIPT_DIR}/..\n\ncd ${ROOT_DIR}\nmake evpp\n"
},
{
"path": "examples/BUILD.bazel",
"chars": 4335,
"preview": "load(\"@rules_cc//cc:defs.bzl\", \"cc_binary\", \"cc_library\")\n\ncc_binary(\n name = \"hloop_test\",\n srcs = [\"hloop_test.c"
},
{
"path": "examples/CMakeLists.txt",
"chars": 6009,
"preview": "list(APPEND EXAMPLES\n hloop_test\n htimer_test\n pipe_test\n nc\n tinyhttpd\n tinyproxyd\n tcp_client_tes"
},
{
"path": "examples/README.md",
"chars": 1087,
"preview": "## 目录结构\n\n```\n.\n├── consul/ consul服务注册与发现\n├── httpd/ HTTP服务端\n├── jsonrpc/ "
},
{
"path": "examples/consul/consul.cpp",
"chars": 4020,
"preview": "#include \"consul.h\"\n\n#include \"HttpClient.h\"\nusing namespace hv;\n\n#include \"json.hpp\"\nusing json = nlohmann::json;\n\n#def"
},
{
"path": "examples/consul/consul.h",
"chars": 1173,
"preview": "#ifndef CONSUL_H_\n#define CONSUL_H_\n\n#include <vector>\n#include <string.h>\n\ntypedef struct consul_node_s {\n // node\n "
},
{
"path": "examples/consul/main.cpp",
"chars": 1854,
"preview": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"consul.h\"\n\nint main(int argc, char* argv[]) {\n "
},
{
"path": "examples/curl.cpp",
"chars": 10026,
"preview": "/*\n * @build: make examples\n * @server bin/httpd -s restart -d\n * @usage: bin/curl -v www.baidu.com\n * bin/curl "
},
{
"path": "examples/hloop_test.c",
"chars": 3527,
"preview": "/*\n * @build: make examples\n * @usage: bin/hloop_test\n * bin/nc 127.0.0.1 10514\n * nc 127.0.0.1 1051"
},
{
"path": "examples/hmain_test.cpp",
"chars": 6647,
"preview": "#include \"hv.h\"\n#include \"hmain.h\"\n#include \"iniparser.h\"\n\n/*\n * @build: make examples\n * @usage: bin/hmain_test -h\n * "
},
{
"path": "examples/htimer_test.c",
"chars": 1789,
"preview": "#include \"hloop.h\"\n#include \"hbase.h\"\n\nvoid on_timer(htimer_t* timer) {\n printf(\"time=%llus on_timer\\n\", LLU(hloop_no"
},
{
"path": "examples/http_client_test.cpp",
"chars": 5248,
"preview": "/*\n * @build make examples\n *\n * @server bin/http_server_test 8080\n *\n * @client bin/http_client_test\n *\n */\n\n#inclu"
},
{
"path": "examples/http_server_test.cpp",
"chars": 3888,
"preview": "/*\n * sample http server\n * more detail see examples/httpd\n *\n */\n\n#include \"HttpServer.h\"\n#include \"hthread.h\" // im"
},
{
"path": "examples/httpd/handler.cpp",
"chars": 12747,
"preview": "#include \"handler.h\"\n\n#include <thread> // import std::thread\n#include <chrono> // import std::chrono\n\n#include \"hba"
},
{
"path": "examples/httpd/handler.h",
"chars": 2182,
"preview": "#ifndef HV_HTTPD_HANDLER_H\n#define HV_HTTPD_HANDLER_H\n\n#include \"HttpService.h\"\n\nclass Handler {\npublic:\n // headerHa"
},
{
"path": "examples/httpd/httpd.cpp",
"chars": 10069,
"preview": "#include \"hv.h\"\n#include \"hssl.h\"\n#include \"hmain.h\"\n#include \"iniparser.h\"\n\n#include \"HttpServer.h\"\n#include \"hasync.h\""
},
{
"path": "examples/httpd/router.cpp",
"chars": 5971,
"preview": "#include \"router.h\"\n\n#include \"handler.h\"\n#include \"hthread.h\" // import hv_gettid\n#include \"hasync.h\" // import "
},
{
"path": "examples/httpd/router.h",
"chars": 185,
"preview": "#ifndef HV_HTTPD_ROUTER_H\n#define HV_HTTPD_ROUTER_H\n\n#include \"HttpService.h\"\n\nclass Router {\npublic:\n static void Re"
},
{
"path": "examples/jsonrpc/cJSON.c",
"chars": 77791,
"preview": "/*\n Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n Permission is hereby granted, free of charge, to any "
},
{
"path": "examples/jsonrpc/cJSON.h",
"chars": 15828,
"preview": "/*\n Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n Permission is hereby granted, free of charge, to any "
},
{
"path": "examples/jsonrpc/handler.h",
"chars": 2674,
"preview": "#ifndef HV_JSON_RPC_HANDLER_H_\n#define HV_JSON_RPC_HANDLER_H_\n\n#include \"router.h\"\n\nvoid error_response(cJSON* jres, int"
},
{
"path": "examples/jsonrpc/jsonrpc_client.c",
"chars": 4194,
"preview": "/*\n * json rpc client\n *\n * @build make jsonrpc\n * @server bin/jsonrpc_server 1234\n * @client bin/jsonrpc_client 127"
},
{
"path": "examples/jsonrpc/jsonrpc_server.c",
"chars": 3610,
"preview": "/*\n * json rpc server\n *\n * @build make jsonrpc\n * @server bin/jsonrpc_server 1234\n * @client bin/jsonrpc_client 127"
},
{
"path": "examples/jsonrpc/router.h",
"chars": 583,
"preview": "#ifndef HV_JSON_RPC_ROUTER_H_\n#define HV_JSON_RPC_ROUTER_H_\n\n#include \"cJSON.h\"\n\ntypedef void (*jsonrpc_handler)(cJSON* "
},
{
"path": "examples/kcptun/README.md",
"chars": 2353,
"preview": "# Intro\n\n<img src=\"kcptun.png\" alt=\"kcptun\" height=\"300px\"/>\n\n> *Disclaimer: The picture comes from [github.com/xtaci/kc"
},
{
"path": "examples/kcptun/client/main.cpp",
"chars": 11493,
"preview": "/*\n * kcptun client\n *\n * @build: ./configure --with-kcp && make clean && make kcptun examples\n * @tcp_server: "
},
{
"path": "examples/kcptun/server/main.cpp",
"chars": 10279,
"preview": "/*\n * kcptun server\n *\n * @build: ./configure --with-kcp && make clean && make kcptun examples\n * @tcp_server: "
},
{
"path": "examples/kcptun/smux/smux.cpp",
"chars": 2148,
"preview": "#include \"smux.h\"\n\n#define SMUX_USE_LITTLE_ENDIAN 1\n\nint smux_frame_pack(const smux_frame_t* frame, void* buf, int len) "
},
{
"path": "examples/kcptun/smux/smux.h",
"chars": 3623,
"preview": "#ifndef HV_SMUX_H_\n#define HV_SMUX_H_\n\n/*\n * smux: Simple MUltipleXing used by kcptun\n * @see: https://github.com/xtaci/"
}
]
// ... and 171 more files (download for full content)
About this extraction
This page contains the full source code of the ithewei/libhv GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 371 files (3.0 MB), approximately 794.9k tokens, and a symbol index with 2614 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.