Compare commits
246 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
68ffcb2a8a | ||
|
|
2a4eceeeab | ||
|
|
46e3f7df6b | ||
|
|
969c0a160d | ||
|
|
1fd95588ed | ||
|
|
aaeaa2203a | ||
|
|
c895f221da | ||
|
|
be51233c04 | ||
|
|
86866e7c60 | ||
|
|
2e20d95333 | ||
|
|
30ef8fe688 | ||
|
|
f6faea35bd | ||
|
|
d137205777 | ||
|
|
3a029dbe25 | ||
|
|
4b1242a837 | ||
|
|
4615827afd | ||
|
|
f8b8418610 | ||
|
|
b5f4a2aa13 | ||
|
|
0caec598b2 | ||
|
|
6296108fcb | ||
|
|
bd13b67bb6 | ||
|
|
711bb918e7 | ||
|
|
8d25270d32 | ||
|
|
4b6178d9b6 | ||
|
|
ee8089b646 | ||
|
|
04614da70a | ||
|
|
dd90cbd5ae | ||
|
|
4f8ea81333 | ||
|
|
0516791805 | ||
|
|
dc2f8298e7 | ||
|
|
9cdc7b77e3 | ||
|
|
c3fe0158f8 | ||
|
|
6a30714038 | ||
|
|
5ccea20716 | ||
|
|
a8498897e7 | ||
|
|
0a14878bef | ||
|
|
c55e2e2e60 | ||
|
|
4b211160f3 | ||
|
|
112e664980 | ||
|
|
1373126939 | ||
|
|
6cb60c8b30 | ||
|
|
a644c73cd5 | ||
|
|
0fa3f17aa2 | ||
|
|
5e00022c88 | ||
|
|
96d0abc8b0 | ||
|
|
7cced34933 | ||
|
|
cb5062de3f | ||
|
|
e657805327 | ||
|
|
5be58a4414 | ||
|
|
c91b1c7f30 | ||
|
|
35ca79be82 | ||
|
|
405ae15530 | ||
|
|
08a909322c | ||
|
|
e20a54cd11 | ||
|
|
3e31841509 | ||
|
|
28ceccd55c | ||
|
|
36647b91ef | ||
|
|
39b5d81231 | ||
|
|
b6cf043a52 | ||
|
|
5d8f776826 | ||
|
|
0d0399f770 | ||
|
|
34346837c8 | ||
|
|
03daef0f29 | ||
|
|
d98c4d2c94 | ||
|
|
1143cfda1b | ||
|
|
17838cfc45 | ||
|
|
b018bb84e4 | ||
|
|
a1bd4373ff | ||
|
|
63c84386ca | ||
|
|
d9ff2e1a62 | ||
|
|
3396100bc4 | ||
|
|
c53693be69 | ||
|
|
855f602e2f | ||
|
|
fd9a5ae249 | ||
|
|
61d5243678 | ||
|
|
e75a4dda25 | ||
|
|
65bfe5c03c | ||
|
|
b7c3e1f80b | ||
|
|
3fb01ce735 | ||
|
|
f14562b26b | ||
|
|
d4f35909c5 | ||
|
|
1ee2b1ff56 | ||
|
|
cab6e8a20f | ||
|
|
e53f8e1c94 | ||
|
|
23819fcb44 | ||
|
|
51930c855f | ||
|
|
690a6f4feb | ||
|
|
56e4020969 | ||
|
|
e06a9a40a3 | ||
|
|
767d2859f9 | ||
|
|
fa0a273865 | ||
|
|
030a7b8784 | ||
|
|
d2cd54d831 | ||
|
|
9c90f6b5cd | ||
|
|
d1e2f549a7 | ||
|
|
ffa9e1ad97 | ||
|
|
ca64905266 | ||
|
|
6b1f70407c | ||
|
|
5d298156e4 | ||
|
|
37f124ffe7 | ||
|
|
675e47ef43 | ||
|
|
176e4006f6 | ||
|
|
d91d5d91ef | ||
|
|
36eba09bbe | ||
|
|
4ac16540b7 | ||
|
|
ab4da37e72 | ||
|
|
b49dd4e97c | ||
|
|
6fb2e167d6 | ||
|
|
4b633a7c2a | ||
|
|
29a854e5d6 | ||
|
|
d49331426a | ||
|
|
fc3b88c2d6 | ||
|
|
fa8b8c5463 | ||
|
|
34ff461506 | ||
|
|
4d850336a9 | ||
|
|
a3eb3de9d9 | ||
|
|
c390f1c9c9 | ||
|
|
e30d191b4a | ||
|
|
d315792cc8 | ||
|
|
8ac3ef77bf | ||
|
|
ab46826072 | ||
|
|
73f88ee92d | ||
|
|
a52f59f629 | ||
|
|
848120d15b | ||
|
|
2fc5ea8bdd | ||
|
|
734f5e5448 | ||
|
|
da55d8ac32 | ||
|
|
2de5c3681f | ||
|
|
37badbee7c | ||
|
|
1f90d9ab93 | ||
|
|
33f2bd5648 | ||
|
|
bac0ab888d | ||
|
|
a557194e9f | ||
|
|
f0d29bc624 | ||
|
|
808cda5a6b | ||
|
|
1fa59df3f5 | ||
|
|
c2b5e9cc92 | ||
|
|
e41aee6dd0 | ||
|
|
f199b6acba | ||
|
|
a8886a1a95 | ||
|
|
38f47a28fa | ||
|
|
60d93b7022 | ||
|
|
b38e96e268 | ||
|
|
88a1f6ecb7 | ||
|
|
ae37ae4e40 | ||
|
|
4fd793b183 | ||
|
|
3288e55453 | ||
|
|
e9fa00409c | ||
|
|
60427893f2 | ||
|
|
ecfa12eb42 | ||
|
|
f8a2dfaf3a | ||
|
|
ae0d65b31f | ||
|
|
c2aac15b29 | ||
|
|
7ff52050dc | ||
|
|
b71a7c2490 | ||
|
|
36671d76c0 | ||
|
|
5130aabeb5 | ||
|
|
bacf92da68 | ||
|
|
757b5db65a | ||
|
|
f3a0668217 | ||
|
|
6d1bbbc4df | ||
|
|
c31106689a | ||
|
|
ce522f5675 | ||
|
|
6bd859747a | ||
|
|
7d5f53aebb | ||
|
|
f28efdf2b1 | ||
|
|
a9a75c6554 | ||
|
|
26f49d26db | ||
|
|
508ddd60e0 | ||
|
|
08b908273a | ||
|
|
8402967a0e | ||
|
|
a2e4264b01 | ||
|
|
ce057a05a7 | ||
|
|
7515c15123 | ||
|
|
60871860ae | ||
|
|
f8d065b09e | ||
|
|
2f2e64ae31 | ||
|
|
a4812dd596 | ||
|
|
2e420e921c | ||
|
|
99972f257a | ||
|
|
8e4ca75d36 | ||
|
|
360019d1a4 | ||
|
|
204c086a03 | ||
|
|
316834ffd0 | ||
|
|
aefbd2e062 | ||
|
|
ff6f60f079 | ||
|
|
b2a34fa18f | ||
|
|
984192c200 | ||
|
|
5747426565 | ||
|
|
0f78a61082 | ||
|
|
fa852f0b7d | ||
|
|
ff9ecd1b48 | ||
|
|
620c05b6bc | ||
|
|
5fffc80367 | ||
|
|
52ce3d69b4 | ||
|
|
259592e35c | ||
|
|
8866fc3a3a | ||
|
|
3dca97a235 | ||
|
|
9511680227 | ||
|
|
acb79bcf1f | ||
|
|
75adc0a669 | ||
|
|
2ef0200276 | ||
|
|
7940a4f949 | ||
|
|
81779637ba | ||
|
|
91d6129426 | ||
|
|
d333533639 | ||
|
|
2429f79721 | ||
|
|
044626152c | ||
|
|
0d7643ceb1 | ||
|
|
0e581ebf6f | ||
|
|
2fcfa6a001 | ||
|
|
546dfb74d3 | ||
|
|
a02a5a19c7 | ||
|
|
09b67f7dc6 | ||
|
|
731584cbd3 | ||
|
|
25a994213f | ||
|
|
c4a9f4c97e | ||
|
|
a56d0d4d58 | ||
|
|
9f01265981 | ||
|
|
1e96d85f88 | ||
|
|
a668a6deff | ||
|
|
9ae47ffaa4 | ||
|
|
8d1c6f69ca | ||
|
|
4bcc36489b | ||
|
|
e9e2bf759a | ||
|
|
c6e3af8ac8 | ||
|
|
5ab2ac455d | ||
|
|
ddc3aff29b | ||
|
|
8f75d7c40c | ||
|
|
3c02e4fbc4 | ||
|
|
5b2b3a63ab | ||
|
|
b96e3d9364 | ||
|
|
f9636ce89c | ||
|
|
c1b7585cd5 | ||
|
|
6f350a33d5 | ||
|
|
b3efc1087a | ||
|
|
e57a99cf6a | ||
|
|
571de7556d | ||
|
|
2ffa39e7cb | ||
|
|
1aba513a05 | ||
|
|
5d0d1f105e | ||
|
|
cb95f86b08 | ||
|
|
7028aa3baa | ||
|
|
94314af51a | ||
|
|
b587a2d30f | ||
|
|
f2e482aa2e |
75
.circleci/config.yml
Normal file
75
.circleci/config.yml
Normal file
@@ -0,0 +1,75 @@
|
||||
#write a circle config file to compile xfrpc project
|
||||
# the xfrpc project is a c project
|
||||
# to compile the project, we need to install some dependencies
|
||||
# in ubuntu 22.04, we need to install the following dependencies
|
||||
# 1. gcc
|
||||
# 2. cmake
|
||||
# 3. libevent-dev
|
||||
# 4. libjson-c
|
||||
# 5. openssl
|
||||
# 6. libz-dev
|
||||
# the following is the config file
|
||||
|
||||
version: 2.1
|
||||
jobs:
|
||||
build:
|
||||
docker:
|
||||
- image: ubuntu:22.04
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: install dependencies
|
||||
command: |
|
||||
apt-get update
|
||||
apt-get install -y gcc cmake libevent-dev libjson-c-dev libssl-dev libz-dev
|
||||
|
||||
- run:
|
||||
name: install go-shadowsocks
|
||||
command: |
|
||||
# install wget and tar
|
||||
apt-get install -y wget tar
|
||||
# download the go-shadowsocks project
|
||||
wget https://github.com/shadowsocks/go-shadowsocks2/releases/download/v0.1.5/shadowsocks2-linux.tgz
|
||||
# unzip the project
|
||||
tar -zxvf shadowsocks2-linux.tgz
|
||||
# move the shadowsocks2-linux to build folder
|
||||
mv shadowsocks2-linux /usr/bin/shadowsocks2-linux
|
||||
|
||||
- run:
|
||||
name: run xfrpc
|
||||
command: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
# generate ini file for xfrpc
|
||||
# the ini file is to configure the xfrpc
|
||||
# the xfrpc will connect to frps server
|
||||
# the frps server is running on from environment variable XFRPC_SERVER
|
||||
# the frps server is listening on port from environment variable FRPS_PORT
|
||||
# the frps server is using the token from environment variable TOKEN
|
||||
# xfrpc add a proxy named chatgptd
|
||||
# the proxy is listening on port 1080
|
||||
# xfrpc will connect to frps server and forward the traffic to the proxy
|
||||
# the proxy will forward the traffic to the shadowsocks-libev
|
||||
# the shadowsocks-libev will forward the traffic to the internet
|
||||
echo "[common]" > xfrpc.ini
|
||||
echo "server_addr = $XFRPC_SERVER" >> xfrpc.ini
|
||||
echo "server_port = $FRPS_PORT" >> xfrpc.ini
|
||||
echo "token = $TOKEN" >> xfrpc.ini
|
||||
echo "[chatgptd]" >> xfrpc.ini
|
||||
echo "type = tcp" >> xfrpc.ini
|
||||
echo "local_ip = 127.0.0.1" >> xfrpc.ini
|
||||
echo "local_port = 1080" >> xfrpc.ini
|
||||
echo "remote_port = 1980" >> xfrpc.ini
|
||||
# run go-shadowsocks2
|
||||
shadowsocks2-linux -s "ss://AEAD_CHACHA20_POLY1305:$SS_PASSWD@:1080" -verbose &
|
||||
# run xfrpc in debug mode
|
||||
cat xfrpc.ini
|
||||
./xfrpc -c xfrpc.ini -f -d 7
|
||||
|
||||
- store_artifacts:
|
||||
path: build/xfrpc
|
||||
destination: xfrpc
|
||||
|
||||
# the above config file is to compile the xfrpc project
|
||||
30
.github/workflows/linux.yml
vendored
Normal file
30
.github/workflows/linux.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
name: compile xfrpc in ubuntu-latest
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: prepare build environment
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libjson-c-dev libevent-dev libssl-dev
|
||||
|
||||
- name: compile xfrpc
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -37,9 +37,11 @@ CMakeFiles/
|
||||
CMakeCache.txt
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
install_manifest.txt
|
||||
|
||||
# bin generated
|
||||
xfrp_client
|
||||
xfrpc
|
||||
xfrp_test_server
|
||||
bin
|
||||
.vscode
|
||||
build
|
||||
|
||||
@@ -1,44 +1,117 @@
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
|
||||
project(xfrp C)
|
||||
|
||||
set(src_xfrp_client
|
||||
|
||||
if (THIRDPARTY_STATIC_BUILD STREQUAL "ON" OR THIRDPARTY_STATIC_BUILD STREQUAL "mips" OR THIRDPARTY_STATIC_BUILD STREQUAL "arm")
|
||||
add_subdirectory(${PROJECT_SOURCE_DIR}/thirdparty/)
|
||||
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/include/libevent)
|
||||
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/include/)
|
||||
link_directories(${PROJECT_SOURCE_DIR}/thirdparty/libs/)
|
||||
set(static_libs dl pthread)
|
||||
else()
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
|
||||
|
||||
find_package(LibEvent)
|
||||
if(NOT LibEvent_FOUND)
|
||||
message(FATAL_ERROR "LibEvent not found!")
|
||||
endif(NOT LibEvent_FOUND)
|
||||
|
||||
find_package(OpenSSL)
|
||||
if(NOT OPENSSL_FOUND)
|
||||
message(FATAL_ERROR "OpenSSL not found!")
|
||||
endif(NOT OPENSSL_FOUND)
|
||||
|
||||
find_package(JSON-C REQUIRED)
|
||||
include_directories(${JSON-C_INCLUDE_DIR})
|
||||
endif(THIRDPARTY_STATIC_BUILD)
|
||||
|
||||
macro(check_asan _RESULT)
|
||||
include(CheckCSourceRuns)
|
||||
set(CMAKE_REQUIRED_FLAGS "-fsanitize=address")
|
||||
check_c_source_runs(
|
||||
[====[
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
]====]
|
||||
${_RESULT}
|
||||
)
|
||||
unset(CMAKE_REQUIRED_FLAGS)
|
||||
endmacro()
|
||||
|
||||
# Enable address sanitizer
|
||||
option(ENABLE_SANITIZER "Enable sanitizer(Debug+Gcc/Clang/AppleClang)" ON)
|
||||
if(ENABLE_SANITIZER AND NOT MSVC)
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
check_asan(HAS_ASAN)
|
||||
if(HAS_ASAN)
|
||||
message(WARNING "add sanitizer")
|
||||
set(asan_c_flags "-fsanitize=address -fsanitize=leak")
|
||||
set(asan_c_libs "asan")
|
||||
else()
|
||||
message(WARNING "sanitizer is no supported with current tool-chains")
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "Sanitizer supported only for debug type")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(src_xfrpc
|
||||
main.c
|
||||
client.c
|
||||
config.c
|
||||
control.c
|
||||
frame.c
|
||||
ini.c
|
||||
msg.c
|
||||
xfrp_client.c
|
||||
xfrpc.c
|
||||
debug.c
|
||||
zip.c
|
||||
commandline.c
|
||||
crypto.c
|
||||
fastpbkdf2.c
|
||||
utils.c
|
||||
session.c
|
||||
common.c
|
||||
login.c
|
||||
proxy_tcp.c
|
||||
proxy_udp.c
|
||||
proxy_ftp.c
|
||||
proxy.c
|
||||
tcpmux.c
|
||||
tcp_redir.c
|
||||
mongoose.c
|
||||
)
|
||||
|
||||
|
||||
set(src_xfrpc_plugins
|
||||
plugins/telnetd.c
|
||||
plugins/instaloader.c
|
||||
plugins/httpd.c
|
||||
plugins/youtubedl.c)
|
||||
|
||||
set(libs
|
||||
ssl
|
||||
crypto
|
||||
event
|
||||
z
|
||||
m
|
||||
json-c)
|
||||
json-c
|
||||
crypt
|
||||
pthread)
|
||||
|
||||
set(test_libs
|
||||
event
|
||||
)
|
||||
|
||||
ADD_DEFINITIONS(-Wall -g --std=gnu99 -Wmissing-declarations)
|
||||
ADD_DEFINITIONS(-Wall -g -Wno-deprecated-declarations --std=gnu99 ${asan_c_flags})
|
||||
|
||||
add_executable(xfrp_client ${src_xfrp_client})
|
||||
target_link_libraries(xfrp_client ${libs})
|
||||
if (STATIC_BUILD STREQUAL "ON")
|
||||
add_link_options(-static)
|
||||
endif (STATIC_BUILD)
|
||||
|
||||
install(TARGETS xfrp_client
|
||||
add_executable(xfrpc ${src_xfrpc} ${src_xfrpc_plugins})
|
||||
target_link_libraries(xfrpc ${libs} ${static_libs} ${asan_c_libs})
|
||||
|
||||
install(TARGETS xfrpc
|
||||
RUNTIME DESTINATION bin
|
||||
)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Contributing
|
||||
================================================================================
|
||||
|
||||
If you want to contribute to [xfrp](https://github.com/kuntengrom/xfrp), please follow these simple rules:
|
||||
If you want to contribute to [xfrpc](https://github.com/liudf0716/xfrpc), please follow these simple rules:
|
||||
|
||||
1. Press the fork button:
|
||||
|
||||
@@ -27,7 +27,7 @@ If you want to contribute to [xfrp](https://github.com/kuntengrom/xfrp), please
|
||||
6. Commit and push your changes, then make a pull request from Github.
|
||||
|
||||
git commit --signoff
|
||||
git push -f
|
||||
git push
|
||||
|
||||
7. Awaiting review, if accepted, merged!
|
||||
|
||||
|
||||
333
README.md
333
README.md
@@ -1,73 +1,297 @@
|
||||

|
||||
|
||||
[![Build Status][1]][2]
|
||||
[![license][3]][4]
|
||||
[![Supported][7]][8]
|
||||
[![PRs Welcome][5]][6]
|
||||
[![Issue Welcome][9]][10]
|
||||
[![OpenWRT][11]][12]
|
||||
[![KunTeng][13]][14]
|
||||

|
||||
|
||||
[1]: https://img.shields.io/travis/KunTengRom/xfrp.svg?style=plastic
|
||||
[2]: https://travis-ci.org/KunTengRom/xfrp
|
||||
[3]: https://img.shields.io/badge/license-GPLV3-brightgreen.svg?style=plastic
|
||||
[4]: https://github.com/KunTengRom/xfrp/blob/master/LICENSE
|
||||
[5]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=plastic
|
||||
[6]: https://github.com/KunTengRom/xfrp/pulls
|
||||
[7]: https://img.shields.io/badge/XFRPS-Supported-blue.svg?style=plastic
|
||||
[8]: https://github.com/KunTengRom/xfrps
|
||||
[9]: https://img.shields.io/badge/Issues-welcome-brightgreen.svg?style=plastic
|
||||
[10]: https://github.com/KunTengRom/xfrp/issues/new
|
||||
[11]: https://img.shields.io/badge/Platform-%20OpenWRT%20%7CLEDE%20-brightgreen.svg?style=plastic
|
||||
[12]: https://github.com/KunTengRom/LEDE
|
||||
[13]: https://img.shields.io/badge/KunTeng-Inside-blue.svg?style=plastic
|
||||
[14]: http://rom.kunteng.org
|
||||
|
||||
## What is xfrp and why start xfrp
|
||||
## What is xfrpc
|
||||
|
||||
xfrp was [xfrps](https://github.com/KunTengRom/xfrp) client implemented by c for OpenWRT system
|
||||
The xfrpc project is an implementation of frp client written in C language for OpenWRT and IOT system. The main motivation of this project is to provide a lightweight solution for devices with limited resources such as OpenWRT devices which often have limited ROM and RAM space. The project aims to provide a frp client that uses less space and memory than other available options.
|
||||
|
||||
The motivation to start xfrp project is that we are OpenWRTer, and openwrt usually ran in device which has little ROM and RAM space, however golang always need more space and memory; therefore we start xfrp project
|
||||
## Development Status
|
||||
|
||||
## Compile
|
||||
xfrpc partially compitable with latest frp release feature, It targets to fully compatible with latest frp release.
|
||||
|
||||
xfrp need [libevent](https://github.com/libevent/libevent) [openssl-dev](https://github.com/openssl/openssl) and [json-c](https://github.com/json-c/json-c) support
|
||||
the following table is detail compatible feature:
|
||||
|
||||
Before compile xfrp, please install `libevent` `openssl-dev` and `json-c` in your system.
|
||||
| Feature | xfrpc | frpc |
|
||||
| ------------- | ------------- | ---------|
|
||||
| tcp | Yes | Yes |
|
||||
| tcpmux | Yes | Yes |
|
||||
| http | Yes | Yes |
|
||||
| https | Yes | Yes |
|
||||
| custom_domains | Yes | Yes |
|
||||
| subdomain | Yes | Yes |
|
||||
| socks5 | Yes | No |
|
||||
| use_encryption | No | Yes |
|
||||
| use_compression | No | Yes |
|
||||
| udp | No | Yes |
|
||||
| p2p | No | Yes |
|
||||
| xtcp | No | Yes |
|
||||
| stcp | No | Yes |
|
||||
|
||||
|
||||
|
||||
## Architecture
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
## Sequence Diagram
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
title: xfrpc与frps通信交互时序图
|
||||
participant 本地服务
|
||||
participant xfrpc
|
||||
participant frps
|
||||
participant 远程访问用户
|
||||
|
||||
xfrpc ->> frps : TypeLogin Message
|
||||
frps ->> xfrpc : TypeLoginResp Message
|
||||
Note right of frps : 根据Login信息里面的pool值,决定给xfrpc发送几条TypeReqWorkConn请求信息
|
||||
frps ->> xfrpc : frps aes-128-cfb iv[16] data
|
||||
frps -->> xfrpc : TypeReqWorkConn Message
|
||||
loop 根据Login中的PoolCount创建工作连接数
|
||||
xfrpc -->> frps : TypeNewWorkConn Message
|
||||
Note left of xfrpc : 与服务器创建代理服务工作连接,并请求新的工作连接请求
|
||||
Note right of frps : 处理xfrpc端发送的TypeNewWorkConn消息,注册该工作连接到连接池中
|
||||
frps ->> xfrpc : TypeStartWorkConn Message
|
||||
Note left of xfrpc : 将新创建的工作连接与代理的本地服务连接做绑定
|
||||
end
|
||||
xfrpc ->> frps : xfrpc aes-128-cfb iv[16] data
|
||||
loop 用户配置的代理服务数
|
||||
xfrpc -->> frps : TypeNewProxy Message
|
||||
frps -->> xfrpc : NewProxyResp Message
|
||||
end
|
||||
|
||||
loop 心跳包检查
|
||||
xfrpc -->> frps : TypePing Message
|
||||
frps -->> xfrpc : TypePong Message
|
||||
end
|
||||
|
||||
远程访问用户 ->> frps : 发起访问
|
||||
frps ->> xfrpc : TypeStartWorkconn Message
|
||||
loop 远程访问用户与本地服务之间的交互过程
|
||||
frps ->> xfrpc : 用户数据
|
||||
xfrpc ->> 本地服务 : 用户数据
|
||||
本地服务 ->> xfrpc : 本地服务数据
|
||||
xfrpc ->> frps : 本地服务数据
|
||||
frps ->> 远程访问用户 : 本地服务数据
|
||||
end
|
||||
|
||||
```
|
||||
|
||||
## How to build
|
||||
|
||||
### Build on Ubuntu 20.04.3 LTS
|
||||
|
||||
To run xfrpc on Ubuntu 20.04 LTS, you will need to have the following libraries installed: libevent, openssl-dev, and json-c. Use the following command in your terminal to install these libraries:
|
||||
|
||||
```
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libjson-c-dev libevent-dev libssl-dev
|
||||
```
|
||||
|
||||
Once the required libraries are installed, you can download the xfrpc source code by forking the xfrpc repository on GitHub and then cloning it to your local machine using the following command:
|
||||
|
||||
```
|
||||
git clone https://github.com/${YOUR_GITHUB_ACCOUNT_NAME}/xfrpc.git
|
||||
```
|
||||
|
||||
Navigate to the xfrp directory and create a build directory by using these commands:
|
||||
|
||||
```
|
||||
cd xfrp
|
||||
mkdir build
|
||||
```
|
||||
Use the following commands to build and install xfrpc:
|
||||
|
||||
```
|
||||
cmake ..
|
||||
make
|
||||
```
|
||||
This will compile xfrpc and create an executable in the build directory. You can then run xfrpc using the executable by running the appropriate command in terminal.
|
||||
|
||||
### Build xfrpc by Built-in thirdparty
|
||||
|
||||
use Built-in thirdparty build xfrpc.
|
||||
|
||||
require cmake version > 3.1.
|
||||
|
||||
To build xfrpc using the built-in third-party libraries, you can fork the xfrpc repository on GitHub and then clone it locally. Then, navigate to the xfrp directory, create a build directory, and use cmake to configure the build.
|
||||
|
||||
```shell
|
||||
git clone https://github.com/KunTengRom/xfrp.git
|
||||
git clone https://github.com/${YOUR_GITHUB_ACCOUNT_NAME}/xfrpc.git
|
||||
cd xfrp
|
||||
cmake .
|
||||
mkdir build
|
||||
cmake -D THIRDPARTY_STATIC_BUILD=ON ..
|
||||
make
|
||||
```
|
||||
|
||||
## Quick start
|
||||
By setting THIRDPARTY_STATIC_BUILD=ON the build process will use the libraries that are included in the xfrpc source code, instead of using the libraries installed on your system.
|
||||
|
||||
The THIRDPARTY_STATIC_BUILD parameter is default set to OFF, which means that by default the build process will use the libraries installed on your system.
|
||||
|
||||
Run in debug mode :
|
||||
It's important to note that you will need cmake version greater than 3.1 to use this feature.
|
||||
|
||||
```shell
|
||||
xfrp_client -c frpc_mini.ini -f -d 7
|
||||
### Cross-compile xfrpc by Built-in thirdparty
|
||||
|
||||
The method of compiling arm architecture or mips architecture xfrpc under x86 architecture is as follows.
|
||||
|
||||
Test on Ubuntu 22.04 LTS
|
||||
|
||||
Cross-compile mips architecture xfrpc(only support linux mips, irix mips don't supported)
|
||||
If can't run in special mips architecture, Modify the CMakeLists.txt in the thirdparty folder and change the linux-mips32 string to linux-generic32.After modify can work.
|
||||
```
|
||||
sudo apt-get install gcc-mips-linux-gnu # install mips-gcc compiler
|
||||
mkdir build && cd build
|
||||
cmake -DTHIRDPARTY_STATIC_BUILD=mips -DCMAKE_C_COMPILER=mips-linux-gnu-gcc ..
|
||||
make
|
||||
```
|
||||
|
||||
Run in release mode :
|
||||
CMAKE_C_COMPILER flag is the path of your cross compiler.I recommend that you put this in an environment variable.
|
||||
|
||||
```shell
|
||||
xfrp_client -c frpc_mini.ini -d 0
|
||||
Cross-compile arm architecture xfrpc
|
||||
```
|
||||
sudo apt-get install arm-linux-gnueabihf-gcc
|
||||
mkdir build && cd build
|
||||
cmake -DTHIRDPARTY_STATIC_BUILD=arm -DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc ..
|
||||
make
|
||||
```
|
||||
|
||||
----
|
||||
### Build static binary in Alpine container
|
||||
|
||||
## Todo list
|
||||
Under project root directory
|
||||
|
||||
- support compression
|
||||
- support encrypt
|
||||
```shell
|
||||
$ DOCKER_BUILDKIT=1 docker build --output out . -f docker/Dockerfile
|
||||
|
||||
$ ls out/
|
||||
xfrpc
|
||||
```
|
||||
|
||||
### Build on OpenWrt master
|
||||
|
||||
xfrpc is included in the OpenWrt community since version 1.04.515, which allows users to easily include it in their custom firmware images. It is recommended to use the latest version of xfrpc as it may have bug fixes and new features.
|
||||
|
||||
To include xfrpc in your OpenWrt firmware image, you can use the make menuconfig command to open the configuration menu. In the menu, navigate to "Network" and select "Web Servers/Proxies" and then select xfrpc. This will include xfrpc in the firmware image that will be built.
|
||||
|
||||
### Build xfrpc with asan(For detect memory leak)
|
||||
|
||||
When encountering a segment fault, please use the following command to compile xfrpc:
|
||||
|
||||
```shell
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug ..
|
||||
```
|
||||
|
||||
Now your xfrpc can detect memory leak.We will add it in ci flow in future.
|
||||
|
||||
## Quick start for use
|
||||
|
||||
**before using xfrpc, you should get frps server: [frps](https://github.com/fatedier/frp/releases)**
|
||||
|
||||
frps is a server-side component of the FRP (Fast Reverse Proxy) system and it is used to forward incoming connections to xfrpc.
|
||||
|
||||
+ frps
|
||||
|
||||
To run frps, you can use the following command, providing it with the path to the frps configuration file:
|
||||
|
||||
```
|
||||
./frps -c frps.ini
|
||||
```
|
||||
|
||||
A sample frps.ini configuration file is provided in the example, which binds frps to listen on port 7000.
|
||||
|
||||
```
|
||||
# frps.ini
|
||||
[common]
|
||||
bind_port = 7000
|
||||
```
|
||||
|
||||
+ xfrpc tcp support
|
||||
|
||||
xfrpc is a client-side component of the FRP system and it can be used to forward TCP connections. To forward incoming TCP connections to a local service, you can configure xfrpc with the following example in xfrpc_mini.ini file
|
||||
|
||||
```
|
||||
#xfrpc_mini.ini
|
||||
[common]
|
||||
server_addr = your_server_ip
|
||||
server_port = 7000
|
||||
|
||||
[ssh]
|
||||
type = tcp
|
||||
local_ip = 127.0.0.1
|
||||
local_port = 22
|
||||
remote_port = 6128
|
||||
```
|
||||
|
||||
This configuration tells the frp server (frps) to forward incoming connections on remote port 6128 to the xfrpc client. The xfrpc client, in turn, will forward these connections to the local service running on IP address 127.0.0.1 and port 22.
|
||||
|
||||
+ xfrpc http&https support
|
||||
|
||||
Supporting HTTP and HTTPS in xfrpc requires additional configuration compared to supporting just TCP. In the frps.ini configuration file, the vhost_http_port and vhost_https_port options must be added to specify the ports that the frp server (frps) will listen on for incoming HTTP and HTTPS connections.
|
||||
|
||||
```
|
||||
# frps.ini
|
||||
[common]
|
||||
bind_port = 7000
|
||||
vhost_http_port = 80
|
||||
vhost_https_port = 443
|
||||
```
|
||||
|
||||
It is important to ensure that the xfrpc client is properly configured to communicate with the frp server by specifying the correct server address and port in the xfrpc configuration file.
|
||||
|
||||
```
|
||||
# xfrpc_mini.ini
|
||||
[common]
|
||||
server_addr = x.x.x.x
|
||||
server_port = 7000
|
||||
|
||||
[http]
|
||||
type = http
|
||||
local_port = 80
|
||||
local_ip = 127.0.0.1
|
||||
custom_domains = www.example.com
|
||||
|
||||
[https]
|
||||
type = https
|
||||
local_port = 443
|
||||
local_ip = 127.0.0.1
|
||||
custom_domains = www.example.com
|
||||
```
|
||||
|
||||
The FRP server (frps) will forward incoming HTTP and HTTPS connections to the domain "www.example.com" to the location where xfrpc is running on the local IP and port specified in the configuration file (127.0.0.1:80 and 127.0.0.1:443 respectively).
|
||||
|
||||
It is important to note that the domain name "www.example.com" should be pointed to the public IP address of the FRP server (frps) so that when a user's HTTP and HTTPS connections visit the domain, the FRP server can forward those connections to the xfrpc client. This can be done by configuring a DNS server or by using a dynamic DNS service.
|
||||
|
||||
+ Run in debug mode
|
||||
|
||||
In order to troubleshooting problem when run xfrpc, you can use debug mode. which has more information when running.
|
||||
|
||||
```shell
|
||||
xfrpc -c frpc_mini.ini -f -d 7
|
||||
```
|
||||
|
||||
+ Run in release mode :
|
||||
|
||||
```shell
|
||||
xfrpc -c frpc_mini.ini -d 0
|
||||
```
|
||||
|
||||
It is important to note that running xfrpc in release mode will generate less log output and will run faster than in debug mode, so it is the recommended way to run xfrpc in production environment.
|
||||
|
||||
## Openwrt luci configure ui
|
||||
|
||||
If you're running xfrpc on an OpenWRT device, luci-app-xfrpc is a good option to use as it provides a web-based interface for configuring and managing xfrpc. luci-app-xfrpc is a module for the LuCI web interface, which is the default web interface for OpenWRT.
|
||||
|
||||
luci-app-xfrpc was adopted by the LuCI project, which is the official web interface for OpenWRT. This means that it is a supported and well-maintained option for managing xfrpc on OpenWRT devices.
|
||||
|
||||
luci-app-xfrpc can be installed via the opkg package manager on OpenWRT and provides a user-friendly interface for configuring the xfrpc client, including options for setting up multiple connections, custom domains and more.
|
||||
|
||||
## How to contribute our project
|
||||
|
||||
See [CONTRIBUTING](https://github.com/KunTengRom/xfrp/blob/master/CONTRIBUTING.md) for details on submitting patches and the contribution workflow.
|
||||
See [CONTRIBUTING](https://github.com/liudf0716/xfrpc/blob/master/CONTRIBUTING.md) for details on submitting patches and the contribution workflow.
|
||||
|
||||
## Contact
|
||||
|
||||
@@ -75,3 +299,28 @@ QQ群 : [331230369](https://jq.qq.com/?_wv=1027&k=47QGEhL)
|
||||
|
||||
|
||||
## Please support us and star our project
|
||||
|
||||
[](https://star-history.com/#liudf0716/xfrpc&Date)
|
||||
|
||||
## 打赏
|
||||
|
||||
支付宝打赏
|
||||
|
||||

|
||||
|
||||
|
||||
微信打赏
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
<!--
|
||||
|
||||
## 广告
|
||||
|
||||
想学习OpenWrt开发,但是摸不着门道?自学没毅力?基础太差?怕太难学不会?跟着佐大学OpenWrt开发入门培训班助你能学有所成
|
||||
|
||||
报名地址:https://forgotfun.org/2018/04/openwrt-training-2018.html
|
||||
|
||||
-->
|
||||
|
||||
46
azure-pipelines.yml
Normal file
46
azure-pipelines.yml
Normal file
@@ -0,0 +1,46 @@
|
||||
# write a azure pipeline yaml
|
||||
trigger:
|
||||
- master
|
||||
|
||||
pool:
|
||||
vmImage: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
persistCredentials: true
|
||||
|
||||
- script: |
|
||||
# install dependencies
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y gcc cmake libevent-dev libjson-c-dev libssl-dev libz-dev
|
||||
# go to build folder
|
||||
mkdir build
|
||||
cd build
|
||||
# run cmake
|
||||
cmake ..
|
||||
# run make
|
||||
make
|
||||
# enable bbr
|
||||
sudo sysctl -w net.core.default_qdisc=fq
|
||||
sudo sysctl -w net.ipv4.tcp_congestion_control=bbr
|
||||
# generate ini file for xfrpc
|
||||
# the ini file is to configure the xfrpc
|
||||
# the xfrpc will connect to frps server
|
||||
# the frps server is running on from environment variable XFRPC_SERVER
|
||||
# the frps server is listening on port from environment variable FRPS_PORT
|
||||
# the frps server is using the token from environment variable TOKEN
|
||||
# xfrpc add a proxy named chatgptd
|
||||
# the proxy is listening on port 1080
|
||||
# xfrpc will connect to frps server and forward the traffic to the proxy
|
||||
# the proxy will forward the traffic to the go-shadowsocks2
|
||||
# the go-shadowsocks2 will forward the traffic to the internet
|
||||
echo "[common]" > xfrpc.ini
|
||||
echo "server_addr = $(XFRPC_SERVER)" >> xfrpc.ini
|
||||
echo "server_port = $(FRPS_PORT)" >> xfrpc.ini
|
||||
echo "token = $(TOKEN)" >> xfrpc.ini
|
||||
echo "[chatgptd]" >> xfrpc.ini
|
||||
echo "type = socks5" >> xfrpc.ini
|
||||
echo "remote_port = $(REMOTE_PORT)" >> xfrpc.ini
|
||||
# run xfrpc
|
||||
./xfrpc -c xfrpc.ini -f -d 7
|
||||
displayName: 'build and run xfrpc'
|
||||
10
bin/frpc.ini
10
bin/frpc.ini
@@ -1,10 +0,0 @@
|
||||
[common]
|
||||
server_addr = 127.0.0.1
|
||||
server_port = 7001
|
||||
tcp_mux = false
|
||||
|
||||
[G_22]
|
||||
type = tcp
|
||||
local_port = 22
|
||||
remote_port = 20099
|
||||
|
||||
56
cicd/azure-pipelines-xfrpc.yml
Normal file
56
cicd/azure-pipelines-xfrpc.yml
Normal file
@@ -0,0 +1,56 @@
|
||||
# write a azure pipeline yaml
|
||||
trigger:
|
||||
- master
|
||||
|
||||
pool:
|
||||
vmImage: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
persistCredentials: true
|
||||
|
||||
- script: |
|
||||
# install dependencies
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y gcc cmake libevent-dev libjson-c-dev libssl-dev libz-dev
|
||||
# install wget and tar
|
||||
sudo apt-get install -y wget tar
|
||||
# download the go-shadowsocks project
|
||||
wget https://github.com/shadowsocks/go-shadowsocks2/releases/download/v0.1.5/shadowsocks2-linux.tgz
|
||||
# unzip the project
|
||||
tar -zxvf shadowsocks2-linux.tgz
|
||||
# move the shadowsocks2-linux to /usr/bin/shadowsocks2-linux
|
||||
sudo mv shadowsocks2-linux /usr/bin/shadowsocks2-linux
|
||||
# create a build folder
|
||||
mkdir build
|
||||
# go to build folder
|
||||
cd build
|
||||
# run cmake
|
||||
cmake ..
|
||||
# run make
|
||||
make
|
||||
# generate ini file for xfrpc
|
||||
# the ini file is to configure the xfrpc
|
||||
# the xfrpc will connect to frps server
|
||||
# the frps server is running on from environment variable XFRPC_SERVER
|
||||
# the frps server is listening on port from environment variable FRPS_PORT
|
||||
# the frps server is using the token from environment variable TOKEN
|
||||
# xfrpc add a proxy named chatgptd
|
||||
# the proxy is listening on port 1080
|
||||
# xfrpc will connect to frps server and forward the traffic to the proxy
|
||||
# the proxy will forward the traffic to the go-shadowsocks2
|
||||
# the go-shadowsocks2 will forward the traffic to the internet
|
||||
echo "[common]" > xfrpc.ini
|
||||
echo "server_addr = $XFRPC_SERVER" >> xfrpc.ini
|
||||
echo "server_port = $FRPS_PORT" >> xfrpc.ini
|
||||
echo "token = $TOKEN" >> xfrpc.ini
|
||||
echo "[chatgptd]" >> xfrpc.ini
|
||||
echo "type = tcp" >> xfrpc.ini
|
||||
echo "local_ip = 127.0.0.1" >> xfrpc.ini
|
||||
echo "local_port = 1080" >> xfrpc.ini
|
||||
echo "remote_port = $REMOTE_PORT" >> xfrpc.ini
|
||||
# run go-shadowsocks2
|
||||
/usr/bin/shadowsocks2-linux -s "ss://AEAD_CHACHA20_POLY1305:$SS_PASSWD@:1080" -verbose &
|
||||
# run xfrpc
|
||||
./xfrpc -c xfrpc.ini -f -d 7
|
||||
displayName: 'build and run xfrpc'
|
||||
322
client.c
322
client.c
@@ -21,7 +21,7 @@
|
||||
|
||||
/** @file client.c
|
||||
@brief client surrogate for local service
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liudengfeng@kunteng.org>
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
@@ -29,213 +29,226 @@
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <syslog.h>
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include <event2/bufferevent.h>
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/listener.h>
|
||||
#include <event2/util.h>
|
||||
#include <event2/event.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "client.h"
|
||||
#include "uthash.h"
|
||||
#include "control.h"
|
||||
#include "config.h"
|
||||
#include "const.h"
|
||||
#include "uthash.h"
|
||||
#include "zip.h"
|
||||
#include "msg.h"
|
||||
#include "common.h"
|
||||
#include "proxy.h"
|
||||
#include "utils.h"
|
||||
#include "tcpmux.h"
|
||||
|
||||
#define MAX_OUTPUT (512*1024)
|
||||
|
||||
static void drained_writecb(struct bufferevent *bev, void *ctx);
|
||||
static void xfrp_event_cb(struct bufferevent *bev, short what, void *ctx);
|
||||
static struct proxy_client *all_pc = NULL;
|
||||
|
||||
static void
|
||||
xfrp_read_cb(struct bufferevent *bev, void *ctx)
|
||||
xfrp_worker_event_cb(struct bufferevent *bev, short what, void *ctx)
|
||||
{
|
||||
struct bufferevent *partner = ctx;
|
||||
struct evbuffer *src, *dst;
|
||||
size_t len;
|
||||
src = bufferevent_get_input(bev);
|
||||
len = evbuffer_get_length(src);
|
||||
if (!partner) {
|
||||
evbuffer_drain(src, len);
|
||||
return;
|
||||
}
|
||||
dst = bufferevent_get_output(partner);
|
||||
evbuffer_add_buffer(dst, src);
|
||||
|
||||
if (evbuffer_get_length(dst) >= MAX_OUTPUT) {
|
||||
/* We're giving the other side data faster than it can
|
||||
* pass it on. Stop reading here until we have drained the
|
||||
* other side to MAX_OUTPUT/2 bytes. */
|
||||
bufferevent_setcb(partner, xfrp_read_cb, drained_writecb,
|
||||
xfrp_event_cb, bev);
|
||||
bufferevent_setwatermark(partner, EV_WRITE, MAX_OUTPUT/2,
|
||||
MAX_OUTPUT);
|
||||
bufferevent_disable(bev, EV_READ);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
drained_writecb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
struct bufferevent *partner = ctx;
|
||||
|
||||
/* We were choking the other side until we drained our outbuf a bit.
|
||||
* Now it seems drained. */
|
||||
bufferevent_setcb(bev, xfrp_read_cb, NULL, xfrp_event_cb, partner);
|
||||
bufferevent_setwatermark(bev, EV_WRITE, 0, 0);
|
||||
if (partner)
|
||||
bufferevent_enable(partner, EV_READ);
|
||||
}
|
||||
|
||||
static void
|
||||
close_on_finished_writecb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
struct evbuffer *b = bufferevent_get_output(bev);
|
||||
|
||||
if (evbuffer_get_length(b) == 0) {
|
||||
if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
|
||||
debug(LOG_DEBUG, "working connection closed!");
|
||||
bufferevent_free(bev);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
xfrp_event_cb(struct bufferevent *bev, short what, void *ctx)
|
||||
void
|
||||
xfrp_proxy_event_cb(struct bufferevent *bev, short what, void *ctx)
|
||||
{
|
||||
struct bufferevent *partner = ctx;
|
||||
struct proxy_client *client = ctx;
|
||||
assert(client);
|
||||
|
||||
if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
|
||||
debug(LOG_DEBUG, "working connection closed");
|
||||
if (partner) {
|
||||
/* Flush all pending data */
|
||||
xfrp_read_cb(bev, ctx);
|
||||
|
||||
if (evbuffer_get_length(bufferevent_get_output(partner))) {
|
||||
/* We still have to flush data from the other
|
||||
* side, but when that's done, close the other
|
||||
* side. */
|
||||
bufferevent_setcb(partner,
|
||||
NULL, close_on_finished_writecb,
|
||||
xfrp_event_cb, NULL);
|
||||
|
||||
bufferevent_disable(partner, EV_READ);
|
||||
} else {
|
||||
/* We have nothing left to say to the other
|
||||
* side; close it. */
|
||||
bufferevent_free(partner);
|
||||
}
|
||||
if (0 == strcmp(client->ps->proxy_type, "tcp"))
|
||||
debug(LOG_DEBUG, "xfrpc tcp proxy close connect server [%s:%d] stream_id %d: %s",
|
||||
client->ps->local_ip, client->ps->local_port,
|
||||
client->stream_id, strerror(errno));
|
||||
else if (0 == strcmp(client->ps->proxy_type, "socks5"))
|
||||
debug(LOG_DEBUG, "xfrpc socks5 proxy close connect [%d:%d] stream_id %d: %s",
|
||||
client->remote_addr.type, client->remote_addr.port,
|
||||
client->stream_id, strerror(errno));
|
||||
else
|
||||
debug(LOG_DEBUG, "xfrpc proxy close connect server [%s:%d] stream_id %d: %s",
|
||||
client->ps->local_ip, client->ps->local_port,
|
||||
client->stream_id, strerror(errno));
|
||||
if (tmux_stream_close(client->ctl_bev, &client->stream)) {
|
||||
bufferevent_free(bev);
|
||||
client->local_proxy_bev = NULL;
|
||||
}
|
||||
} else if (what & BEV_EVENT_CONNECTED) {
|
||||
debug(LOG_DEBUG, "what [%d] client [%d] connected : %s", what, client->stream_id, strerror(errno));
|
||||
if (client->data_tail_size > 0) {
|
||||
debug(LOG_DEBUG, "send client data ...");
|
||||
send_client_data_tail(client);
|
||||
} else if (is_socks5_proxy(client->ps)) {
|
||||
// if rb is not empty, send data
|
||||
// rb is client->stream.rx_ring
|
||||
struct ring_buffer *rb = &client->stream.rx_ring;
|
||||
if (rb->sz > 0)
|
||||
tx_ring_buffer_write(client->local_proxy_bev, rb, rb->sz);
|
||||
|
||||
client->state = SOCKS5_ESTABLISHED;
|
||||
}
|
||||
bufferevent_free(bev);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
xfrp_decrypt_cb(struct bufferevent *bev, void *ctx)
|
||||
int
|
||||
is_ftp_proxy(const struct proxy_service *ps)
|
||||
{
|
||||
struct bufferevent *partner = ctx;
|
||||
struct evbuffer *src, *dst;
|
||||
src = bufferevent_get_input(bev);
|
||||
dst = bufferevent_get_output(partner);
|
||||
evbuffer_add_buffer(dst, src);
|
||||
if (! ps || ! ps->proxy_type)
|
||||
return 0;
|
||||
|
||||
if (0 == strcmp(ps->proxy_type, "ftp") && ps->remote_data_port > 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
xfrp_encrypt_cb(struct bufferevent *bev, void *ctx)
|
||||
int
|
||||
is_socks5_proxy(const struct proxy_service *ps)
|
||||
{
|
||||
struct bufferevent *partner = ctx;
|
||||
struct evbuffer *src, *dst;
|
||||
size_t len;
|
||||
src = bufferevent_get_input(bev);
|
||||
len = evbuffer_get_length(src);
|
||||
if (len > 0) {
|
||||
dst = bufferevent_get_output(partner);
|
||||
evbuffer_add_buffer(dst, src);
|
||||
}
|
||||
if (! ps || ! ps->proxy_type)
|
||||
return 0;
|
||||
|
||||
if (0 == strcmp(ps->proxy_type, "socks5"))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
is_udp_proxy (const struct proxy_service *ps)
|
||||
{
|
||||
if (! ps || ! ps->proxy_type)
|
||||
return 0;
|
||||
|
||||
if (0 == strcmp(ps->proxy_type, "udp"))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// create frp tunnel for service
|
||||
void start_frp_tunnel(struct proxy_client *client)
|
||||
void
|
||||
start_xfrp_tunnel(struct proxy_client *client)
|
||||
{
|
||||
if (! client->ctl_bev) {
|
||||
debug(LOG_ERR, "proxy client control bev is invalid!");
|
||||
return;
|
||||
}
|
||||
|
||||
struct event_base *base = client->base;
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
struct proxy_service *ps = client->ps;
|
||||
if (! ps) {
|
||||
|
||||
if ( !base ) {
|
||||
debug(LOG_ERR, "service event base get failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !ps ) {
|
||||
debug(LOG_ERR, "service tunnel started failed, no proxy service resource.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (! ps->local_port) {
|
||||
if ( !ps->local_port ) {
|
||||
debug(LOG_ERR, "service tunnel started failed, proxy service resource unvalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
client->local_proxy_bev = connect_server(base, ps->local_ip, ps->local_port);
|
||||
if (!client->local_proxy_bev) {
|
||||
debug(LOG_ERR, "frpc tunnel connect local proxy port [%d] failed!", ps->local_port);
|
||||
bufferevent_free(client->ctl_bev);
|
||||
// if client's proxy type is udp
|
||||
if ( is_udp_proxy(ps) ) {
|
||||
debug(LOG_DEBUG, "start udp proxy tunnel for service [%s:%d]", ps->local_ip, ps->local_port);
|
||||
client->local_proxy_bev = connect_udp_server(base);
|
||||
if ( !client->local_proxy_bev ) {
|
||||
debug(LOG_ERR, "frpc tunnel connect local proxy port [%d] failed!", ps->local_port);
|
||||
del_proxy_client_by_stream_id(client->stream_id);
|
||||
return;
|
||||
}
|
||||
} else if ( !is_socks5_proxy(ps) ) {
|
||||
client->local_proxy_bev = connect_server(base, ps->local_ip, ps->local_port);
|
||||
if ( !client->local_proxy_bev ) {
|
||||
debug(LOG_ERR, "frpc tunnel connect local proxy port [%d] failed!", ps->local_port);
|
||||
del_proxy_client_by_stream_id(client->stream_id);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
debug(LOG_DEBUG, "socks5 proxy client can't connect to remote server here ...");
|
||||
return;
|
||||
}
|
||||
|
||||
debug(LOG_DEBUG, "proxy server [%s:%d] <---> client [%s:%d]",
|
||||
c_conf->server_addr,
|
||||
c_conf->server_port,
|
||||
ps->local_ip ? ps->local_ip:"::1",
|
||||
ps->remote_port,
|
||||
ps->local_ip ? ps->local_ip:"127.0.0.1",
|
||||
ps->local_port);
|
||||
|
||||
bufferevent_setcb(client->ctl_bev,
|
||||
xfrp_decrypt_cb,
|
||||
#define PREDICT_FALSE(x) 0
|
||||
bufferevent_data_cb proxy_s2c_recv, proxy_c2s_recv;
|
||||
if (PREDICT_FALSE(is_ftp_proxy(client->ps))) {
|
||||
proxy_c2s_recv = ftp_proxy_c2s_cb;
|
||||
proxy_s2c_recv = ftp_proxy_s2c_cb;
|
||||
} else if ( is_udp_proxy(ps) ) {
|
||||
proxy_c2s_recv = udp_proxy_c2s_cb;
|
||||
proxy_s2c_recv = udp_proxy_s2c_cb;
|
||||
} else {
|
||||
proxy_c2s_recv = tcp_proxy_c2s_cb; // local service ---> xfrpc
|
||||
proxy_s2c_recv = tcp_proxy_s2c_cb; // frps ---> xfrpc
|
||||
}
|
||||
|
||||
if (!c_conf->tcp_mux) {
|
||||
bufferevent_setcb(client->ctl_bev,
|
||||
proxy_s2c_recv,
|
||||
NULL,
|
||||
xfrp_event_cb,
|
||||
client->local_proxy_bev);
|
||||
xfrp_worker_event_cb,
|
||||
client);
|
||||
bufferevent_enable(client->ctl_bev, EV_READ|EV_WRITE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bufferevent_setcb(client->local_proxy_bev,
|
||||
xfrp_encrypt_cb,
|
||||
proxy_c2s_recv,
|
||||
NULL,
|
||||
xfrp_event_cb,
|
||||
client->ctl_bev);
|
||||
xfrp_proxy_event_cb,
|
||||
client);
|
||||
|
||||
bufferevent_enable(client->ctl_bev, EV_READ|EV_WRITE);
|
||||
bufferevent_enable(client->local_proxy_bev, EV_READ|EV_WRITE);
|
||||
}
|
||||
|
||||
int send_client_data_tail(struct proxy_client *client)
|
||||
int
|
||||
send_client_data_tail(struct proxy_client *client)
|
||||
{
|
||||
int send_l = 0;
|
||||
if (client->data_tail && client->data_tail_size && client->local_proxy_bev) {
|
||||
send_l = bufferevent_write(client->local_proxy_bev, client->data_tail, client->data_tail_size);
|
||||
client->data_tail = NULL;
|
||||
client->data_tail_size = 0;
|
||||
}
|
||||
|
||||
return send_l;
|
||||
}
|
||||
|
||||
void free_proxy_client(struct proxy_client *client)
|
||||
static void
|
||||
free_proxy_client(struct proxy_client *client)
|
||||
{
|
||||
if (client->name) free(client->name);
|
||||
if (client->local_ip) free(client->local_ip);
|
||||
if (client->custom_domains) free(client->custom_domains);
|
||||
if (client->locations) free(client->locations);
|
||||
|
||||
free_base_config(client->bconf);
|
||||
|
||||
evtimer_del(client->ev_timeout);
|
||||
debug(LOG_DEBUG, "free client %d", client->stream_id);
|
||||
if (client->local_proxy_bev) bufferevent_free(client->local_proxy_bev);
|
||||
free(client);
|
||||
}
|
||||
|
||||
void del_proxy_client(struct proxy_client *client)
|
||||
static void
|
||||
del_proxy_client(struct proxy_client *client)
|
||||
{
|
||||
struct proxy_client *all_pc = get_all_pc();
|
||||
if (!client || !all_pc ) {
|
||||
debug(LOG_INFO, "Error: all_pc or client is NULL");
|
||||
debug(LOG_INFO, "all_pc or client is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -244,11 +257,46 @@ void del_proxy_client(struct proxy_client *client)
|
||||
free_proxy_client(client);
|
||||
}
|
||||
|
||||
// Return NULL if proxy service not found with proxy_name
|
||||
struct proxy_service *get_proxy_service(const char *proxy_name)
|
||||
void
|
||||
del_proxy_client_by_stream_id(uint32_t sid)
|
||||
{
|
||||
struct proxy_service *ps = NULL;
|
||||
struct proxy_service *all_ps = get_all_proxy_services();
|
||||
HASH_FIND_STR(all_ps, proxy_name, ps);
|
||||
return ps;
|
||||
}
|
||||
del_stream(sid);
|
||||
|
||||
struct proxy_client *pc = get_proxy_client(sid);
|
||||
del_proxy_client(pc);
|
||||
}
|
||||
|
||||
struct proxy_client *
|
||||
get_proxy_client(uint32_t sid)
|
||||
{
|
||||
struct proxy_client *pc = NULL;
|
||||
HASH_FIND_INT(all_pc, &sid, pc);
|
||||
return pc;
|
||||
}
|
||||
|
||||
struct proxy_client *
|
||||
new_proxy_client()
|
||||
{
|
||||
struct proxy_client *client = calloc(1, sizeof(struct proxy_client));
|
||||
assert(client);
|
||||
client->stream_id = get_next_session_id();
|
||||
init_tmux_stream(&client->stream, client->stream_id, INIT);
|
||||
HASH_ADD_INT(all_pc, stream_id, client);
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
void
|
||||
clear_all_proxy_client()
|
||||
{
|
||||
clear_stream();
|
||||
|
||||
if (!all_pc) return;
|
||||
|
||||
struct proxy_client *client, *tmp;
|
||||
HASH_ITER(hh, all_pc, client, tmp) {
|
||||
HASH_DEL(all_pc, client);
|
||||
free_proxy_client(client);
|
||||
}
|
||||
all_pc = NULL;
|
||||
}
|
||||
|
||||
89
client.h
89
client.h
@@ -20,8 +20,8 @@
|
||||
\********************************************************************/
|
||||
|
||||
/** @file client.h
|
||||
@brief xfrp client proxy client related
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liudengfeng@kunteng.org>
|
||||
@brief xfrpc proxy client related
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
#ifndef _CLIENT_H_
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include "uthash.h"
|
||||
#include "common.h"
|
||||
#include "tcpmux.h"
|
||||
|
||||
struct event_base;
|
||||
struct base_conf;
|
||||
@@ -38,45 +39,54 @@ struct bufferevent;
|
||||
struct event;
|
||||
struct proxy_service;
|
||||
|
||||
#define SOCKS5_ADDRES_LEN 20
|
||||
struct socks5_addr {
|
||||
uint8_t addr[SOCKS5_ADDRES_LEN];
|
||||
uint16_t port;
|
||||
uint8_t type;
|
||||
uint8_t reserve;
|
||||
};
|
||||
|
||||
enum socks5_state {
|
||||
SOCKS5_INIT,
|
||||
SOCKS5_HANDSHAKE,
|
||||
SOCKS5_CONNECT,
|
||||
SOCKS5_ESTABLISHED,
|
||||
};
|
||||
|
||||
struct proxy_client {
|
||||
struct event_base *base;
|
||||
struct bufferevent *ctl_bev;
|
||||
struct bufferevent *local_proxy_bev;
|
||||
struct event *ev_timeout;
|
||||
|
||||
struct bufferevent *ctl_bev; // xfrpc proxy <---> frps
|
||||
struct bufferevent *local_proxy_bev; // xfrpc proxy <---> local service
|
||||
struct base_conf *bconf;
|
||||
char *name; // pointer to bconf->name
|
||||
char *local_ip;
|
||||
char *type;
|
||||
int local_port;
|
||||
int remote_port;
|
||||
int use_encryption;
|
||||
int use_compression;
|
||||
struct tmux_stream stream;
|
||||
|
||||
char *custom_domains;
|
||||
char *subdomain;
|
||||
char *locations;
|
||||
char *host_header_rewrite;
|
||||
char *http_user;
|
||||
char *http_pwd;
|
||||
|
||||
//provate arguments
|
||||
UT_hash_handle hh;
|
||||
uint32_t stream_id;
|
||||
int connected;
|
||||
int work_started;
|
||||
struct proxy_service *ps;
|
||||
unsigned char *data_tail; // storage untrated data
|
||||
unsigned char *data_tail; // storage untreated data
|
||||
size_t data_tail_size;
|
||||
|
||||
// socks5 only
|
||||
struct socks5_addr remote_addr;
|
||||
enum socks5_state state;
|
||||
|
||||
// private arguments
|
||||
UT_hash_handle hh;
|
||||
};
|
||||
|
||||
struct proxy_service {
|
||||
char *proxy_name;
|
||||
char *proxy_type;
|
||||
char *ftp_cfg_proxy_name;
|
||||
int use_encryption;
|
||||
int use_compression;
|
||||
|
||||
// tcp or udp
|
||||
char *local_ip;
|
||||
int remote_port;
|
||||
int remote_data_port;
|
||||
int local_port;
|
||||
|
||||
// http and https only
|
||||
@@ -87,7 +97,18 @@ struct proxy_service {
|
||||
char *http_user;
|
||||
char *http_pwd;
|
||||
|
||||
//provate arguments
|
||||
// load balance
|
||||
char *group;
|
||||
char *group_key;
|
||||
|
||||
// plugin
|
||||
char *plugin;
|
||||
char *plugin_user;
|
||||
char *plugin_pwd;
|
||||
|
||||
char *s_root_dir;
|
||||
|
||||
// private arguments
|
||||
UT_hash_handle hh;
|
||||
};
|
||||
|
||||
@@ -96,14 +117,24 @@ struct proxy_service {
|
||||
// when xfrp client receive that request, it will start
|
||||
// frp tunnel
|
||||
// if client has data-tail(not NULL), client value will be changed
|
||||
void start_frp_tunnel(struct proxy_client *client);
|
||||
void start_xfrp_tunnel(struct proxy_client *client);
|
||||
|
||||
void del_proxy_client(struct proxy_client *client);
|
||||
void del_proxy_client_by_stream_id(uint32_t sid);
|
||||
|
||||
void free_proxy_client(struct proxy_client *client);
|
||||
|
||||
struct proxy_service *get_proxy_service(const char *proxy_name);
|
||||
struct proxy_client *get_proxy_client(uint32_t sid);
|
||||
|
||||
int send_client_data_tail(struct proxy_client *client);
|
||||
|
||||
int is_ftp_proxy(const struct proxy_service *ps);
|
||||
|
||||
int is_socks5_proxy(const struct proxy_service *ps);
|
||||
|
||||
int is_udp_proxy(const struct proxy_service *ps);
|
||||
|
||||
struct proxy_client *new_proxy_client();
|
||||
|
||||
void clear_all_proxy_client();
|
||||
|
||||
void xfrp_proxy_event_cb(struct bufferevent *bev, short what, void *ctx);
|
||||
|
||||
#endif //_CLIENT_H_
|
||||
|
||||
161
cmake/Modules/CMakeParseArguments.cmake
Normal file
161
cmake/Modules/CMakeParseArguments.cmake
Normal file
@@ -0,0 +1,161 @@
|
||||
#.rst:
|
||||
# CMakeParseArguments
|
||||
# -------------------
|
||||
#
|
||||
#
|
||||
#
|
||||
# CMAKE_PARSE_ARGUMENTS(<prefix> <options> <one_value_keywords>
|
||||
# <multi_value_keywords> args...)
|
||||
#
|
||||
# CMAKE_PARSE_ARGUMENTS() is intended to be used in macros or functions
|
||||
# for parsing the arguments given to that macro or function. It
|
||||
# processes the arguments and defines a set of variables which hold the
|
||||
# values of the respective options.
|
||||
#
|
||||
# The <options> argument contains all options for the respective macro,
|
||||
# i.e. keywords which can be used when calling the macro without any
|
||||
# value following, like e.g. the OPTIONAL keyword of the install()
|
||||
# command.
|
||||
#
|
||||
# The <one_value_keywords> argument contains all keywords for this macro
|
||||
# which are followed by one value, like e.g. DESTINATION keyword of the
|
||||
# install() command.
|
||||
#
|
||||
# The <multi_value_keywords> argument contains all keywords for this
|
||||
# macro which can be followed by more than one value, like e.g. the
|
||||
# TARGETS or FILES keywords of the install() command.
|
||||
#
|
||||
# When done, CMAKE_PARSE_ARGUMENTS() will have defined for each of the
|
||||
# keywords listed in <options>, <one_value_keywords> and
|
||||
# <multi_value_keywords> a variable composed of the given <prefix>
|
||||
# followed by "_" and the name of the respective keyword. These
|
||||
# variables will then hold the respective value from the argument list.
|
||||
# For the <options> keywords this will be TRUE or FALSE.
|
||||
#
|
||||
# All remaining arguments are collected in a variable
|
||||
# <prefix>_UNPARSED_ARGUMENTS, this can be checked afterwards to see
|
||||
# whether your macro was called with unrecognized parameters.
|
||||
#
|
||||
# As an example here a my_install() macro, which takes similar arguments
|
||||
# as the real install() command:
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# function(MY_INSTALL)
|
||||
# set(options OPTIONAL FAST)
|
||||
# set(oneValueArgs DESTINATION RENAME)
|
||||
# set(multiValueArgs TARGETS CONFIGURATIONS)
|
||||
# cmake_parse_arguments(MY_INSTALL "${options}" "${oneValueArgs}"
|
||||
# "${multiValueArgs}" ${ARGN} )
|
||||
# ...
|
||||
#
|
||||
#
|
||||
#
|
||||
# Assume my_install() has been called like this:
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub)
|
||||
#
|
||||
#
|
||||
#
|
||||
# After the cmake_parse_arguments() call the macro will have set the
|
||||
# following variables:
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# MY_INSTALL_OPTIONAL = TRUE
|
||||
# MY_INSTALL_FAST = FALSE (this option was not used when calling my_install()
|
||||
# MY_INSTALL_DESTINATION = "bin"
|
||||
# MY_INSTALL_RENAME = "" (was not used)
|
||||
# MY_INSTALL_TARGETS = "foo;bar"
|
||||
# MY_INSTALL_CONFIGURATIONS = "" (was not used)
|
||||
# MY_INSTALL_UNPARSED_ARGUMENTS = "blub" (no value expected after "OPTIONAL"
|
||||
#
|
||||
#
|
||||
#
|
||||
# You can then continue and process these variables.
|
||||
#
|
||||
# Keywords terminate lists of values, e.g. if directly after a
|
||||
# one_value_keyword another recognized keyword follows, this is
|
||||
# interpreted as the beginning of the new option. E.g.
|
||||
# my_install(TARGETS foo DESTINATION OPTIONAL) would result in
|
||||
# MY_INSTALL_DESTINATION set to "OPTIONAL", but MY_INSTALL_DESTINATION
|
||||
# would be empty and MY_INSTALL_OPTIONAL would be set to TRUE therefor.
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2010 Alexander Neundorf <neundorf@kde.org>
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
# (To distribute this file outside of CMake, substitute the full
|
||||
# License text for the above reference.)
|
||||
|
||||
|
||||
if(__CMAKE_PARSE_ARGUMENTS_INCLUDED)
|
||||
return()
|
||||
endif()
|
||||
set(__CMAKE_PARSE_ARGUMENTS_INCLUDED TRUE)
|
||||
|
||||
|
||||
function(CMAKE_PARSE_ARGUMENTS prefix _optionNames _singleArgNames _multiArgNames)
|
||||
# first set all result variables to empty/FALSE
|
||||
foreach(arg_name ${_singleArgNames} ${_multiArgNames})
|
||||
set(${prefix}_${arg_name})
|
||||
endforeach()
|
||||
|
||||
foreach(option ${_optionNames})
|
||||
set(${prefix}_${option} FALSE)
|
||||
endforeach()
|
||||
|
||||
set(${prefix}_UNPARSED_ARGUMENTS)
|
||||
|
||||
set(insideValues FALSE)
|
||||
set(currentArgName)
|
||||
|
||||
# now iterate over all arguments and fill the result variables
|
||||
foreach(currentArg ${ARGN})
|
||||
list(FIND _optionNames "${currentArg}" optionIndex) # ... then this marks the end of the arguments belonging to this keyword
|
||||
list(FIND _singleArgNames "${currentArg}" singleArgIndex) # ... then this marks the end of the arguments belonging to this keyword
|
||||
list(FIND _multiArgNames "${currentArg}" multiArgIndex) # ... then this marks the end of the arguments belonging to this keyword
|
||||
|
||||
if(${optionIndex} EQUAL -1 AND ${singleArgIndex} EQUAL -1 AND ${multiArgIndex} EQUAL -1)
|
||||
if(insideValues)
|
||||
if("${insideValues}" STREQUAL "SINGLE")
|
||||
set(${prefix}_${currentArgName} ${currentArg})
|
||||
set(insideValues FALSE)
|
||||
elseif("${insideValues}" STREQUAL "MULTI")
|
||||
list(APPEND ${prefix}_${currentArgName} ${currentArg})
|
||||
endif()
|
||||
else()
|
||||
list(APPEND ${prefix}_UNPARSED_ARGUMENTS ${currentArg})
|
||||
endif()
|
||||
else()
|
||||
if(NOT ${optionIndex} EQUAL -1)
|
||||
set(${prefix}_${currentArg} TRUE)
|
||||
set(insideValues FALSE)
|
||||
elseif(NOT ${singleArgIndex} EQUAL -1)
|
||||
set(currentArgName ${currentArg})
|
||||
set(${prefix}_${currentArgName})
|
||||
set(insideValues "SINGLE")
|
||||
elseif(NOT ${multiArgIndex} EQUAL -1)
|
||||
set(currentArgName ${currentArg})
|
||||
set(${prefix}_${currentArgName})
|
||||
set(insideValues "MULTI")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
endforeach()
|
||||
|
||||
# propagate the result variables to the caller:
|
||||
foreach(arg_name ${_singleArgNames} ${_multiArgNames} ${_optionNames})
|
||||
set(${prefix}_${arg_name} ${${prefix}_${arg_name}} PARENT_SCOPE)
|
||||
endforeach()
|
||||
set(${prefix}_UNPARSED_ARGUMENTS ${${prefix}_UNPARSED_ARGUMENTS} PARENT_SCOPE)
|
||||
|
||||
endfunction()
|
||||
21
cmake/Modules/FindJSON-C.cmake
Normal file
21
cmake/Modules/FindJSON-C.cmake
Normal file
@@ -0,0 +1,21 @@
|
||||
# JSON-C_FOUND - true if library and headers were found
|
||||
# JSON-C_INCLUDE_DIRS - include directories
|
||||
# JSON-C_LIBRARIES - library directories
|
||||
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(PC_JSON-C QUIET json-c)
|
||||
|
||||
find_path(JSON-C_INCLUDE_DIR json.h
|
||||
HINTS ${PC_JSON-C_INCLUDEDIR} ${PC_JSON-C_INCLUDE_DIRS} PATH_SUFFIXES json-c json)
|
||||
|
||||
find_library(JSON-C_LIBRARY NAMES json-c libjson-c
|
||||
HINTS ${PC_JSON-C_LIBDIR} ${PC_JSON-C_LIBRARY_DIRS})
|
||||
|
||||
set(JSON-C_LIBRARIES ${JSON-C_LIBRARY})
|
||||
set(JSON-C_INCLUDE_DIRS ${JSON-C_INCLUDE_DIR})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
find_package_handle_standard_args(JSON-C DEFAULT_MSG JSON-C_LIBRARY JSON-C_INCLUDE_DIR)
|
||||
|
||||
mark_as_advanced(JSON-C_INCLUDE_DIR JSON-C_LIBRARY)
|
||||
39
cmake/Modules/FindLibEvent.cmake
Normal file
39
cmake/Modules/FindLibEvent.cmake
Normal file
@@ -0,0 +1,39 @@
|
||||
# - Find LibEvent (a cross event library)
|
||||
# This module defines
|
||||
# LIBEVENT_INCLUDE_DIR, where to find LibEvent headers
|
||||
# LIBEVENT_LIB, LibEvent libraries
|
||||
# LibEvent_FOUND, If false, do not try to use libevent
|
||||
|
||||
set(LibEvent_EXTRA_PREFIXES /usr/local /opt/local "$ENV{HOME}")
|
||||
foreach(prefix ${LibEvent_EXTRA_PREFIXES})
|
||||
list(APPEND LibEvent_INCLUDE_PATHS "${prefix}/include")
|
||||
list(APPEND LibEvent_LIB_PATHS "${prefix}/lib")
|
||||
endforeach()
|
||||
|
||||
FIND_PATH(LIBEVENT_INCLUDE_DIR event.h PATHS ${LibEvent_INCLUDE_PATHS})
|
||||
|
||||
FIND_LIBRARY(LIBEVENT_LIB NAMES event PATHS ${LibEvent_LIB_PATHS})
|
||||
FIND_LIBRARY(LIBEVENT_CORE_LIB NAMES event_core PATHS ${LibEvent_LIB_PATHS})
|
||||
FIND_LIBRARY(LIBEVENT_PTHREADS_LIB NAMES event_pthreads PATHS ${LibEvent_LIB_PATHS})
|
||||
FIND_LIBRARY(LIBEVENT_EXTRA_LIB NAMES event_extra PATHS ${LibEvent_LIB_PATHS})
|
||||
FIND_LIBRARY(LIBEVENT_OPENSSL_LIB NAMES event_openssl PATHS ${LibEvent_LIB_PATHS})
|
||||
|
||||
if (LIBEVENT_LIB AND LIBEVENT_INCLUDE_DIR)
|
||||
set(LibEvent_FOUND TRUE)
|
||||
set(LIBEVENT_LIB ${LIBEVENT_LIB})
|
||||
else ()
|
||||
set(LibEvent_FOUND FALSE)
|
||||
endif ()
|
||||
|
||||
if (LibEvent_FOUND)
|
||||
if (NOT LibEvent_FIND_QUIETLY)
|
||||
message(STATUS "Found libevent: ${LIBEVENT_LIB}")
|
||||
endif ()
|
||||
else ()
|
||||
if (LibEvent_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could NOT find libevent.")
|
||||
endif ()
|
||||
message(STATUS "libevent NOT found.")
|
||||
endif ()
|
||||
|
||||
MARK_AS_ADVANCED(LIBEVENT_INCLUDE_DIR LIBEVENT_LIB LIBEVENT_PTHREADS_LIB LIBEVENT_OPENSSL_LIB LIBEVENT_CORE_LIB LIBEVENT_EXTRA_LIB)
|
||||
359
cmake/Modules/FindOpenSSL.cmake
Normal file
359
cmake/Modules/FindOpenSSL.cmake
Normal file
@@ -0,0 +1,359 @@
|
||||
#.rst:
|
||||
# FindOpenSSL
|
||||
# -----------
|
||||
#
|
||||
# Try to find the OpenSSL encryption library
|
||||
#
|
||||
# Once done this will define
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# OPENSSL_ROOT_DIR - Set this variable to the root installation of OpenSSL
|
||||
#
|
||||
#
|
||||
#
|
||||
# Read-Only variables:
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# OPENSSL_FOUND - System has the OpenSSL library
|
||||
# OPENSSL_INCLUDE_DIR - The OpenSSL include directory
|
||||
# OPENSSL_CRYPTO_LIBRARY - The OpenSSL crypto library
|
||||
# OPENSSL_SSL_LIBRARY - The OpenSSL SSL library
|
||||
# OPENSSL_LIBRARIES - All OpenSSL libraries
|
||||
# OPENSSL_VERSION - This is set to $major.$minor.$revision$patch (eg. 0.9.8s)
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2006-2009 Kitware, Inc.
|
||||
# Copyright 2006 Alexander Neundorf <neundorf@kde.org>
|
||||
# Copyright 2009-2011 Mathieu Malaterre <mathieu.malaterre@gmail.com>
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
# (To distribute this file outside of CMake, substitute the full
|
||||
# License text for the above reference.)
|
||||
|
||||
if (UNIX)
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(_OPENSSL QUIET openssl)
|
||||
endif ()
|
||||
|
||||
if (WIN32)
|
||||
# http://www.slproweb.com/products/Win32OpenSSL.html
|
||||
set(_OPENSSL_ROOT_HINTS
|
||||
${OPENSSL_ROOT_DIR}
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (32-bit)_is1;Inno Setup: App Path]"
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;Inno Setup: App Path]"
|
||||
ENV OPENSSL_ROOT_DIR
|
||||
)
|
||||
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
|
||||
set(_OPENSSL_ROOT_PATHS
|
||||
"${_programfiles}/OpenSSL"
|
||||
"${_programfiles}/OpenSSL-Win32"
|
||||
"${_programfiles}/OpenSSL-Win64"
|
||||
"C:/OpenSSL/"
|
||||
"C:/OpenSSL-Win32/"
|
||||
"C:/OpenSSL-Win64/"
|
||||
)
|
||||
unset(_programfiles)
|
||||
else ()
|
||||
set(_OPENSSL_ROOT_HINTS
|
||||
${OPENSSL_ROOT_DIR}
|
||||
ENV OPENSSL_ROOT_DIR
|
||||
)
|
||||
endif ()
|
||||
|
||||
set(_OPENSSL_ROOT_HINTS_AND_PATHS
|
||||
HINTS ${_OPENSSL_ROOT_HINTS}
|
||||
PATHS ${_OPENSSL_ROOT_PATHS}
|
||||
)
|
||||
|
||||
find_path(OPENSSL_INCLUDE_DIR
|
||||
NAMES
|
||||
openssl/ssl.h
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
||||
HINTS
|
||||
${_OPENSSL_INCLUDEDIR}
|
||||
PATH_SUFFIXES
|
||||
include
|
||||
)
|
||||
|
||||
if(WIN32 AND NOT CYGWIN)
|
||||
if(MSVC)
|
||||
# /MD and /MDd are the standard values - if someone wants to use
|
||||
# others, the libnames have to change here too
|
||||
# use also ssl and ssleay32 in debug as fallback for openssl < 0.9.8b
|
||||
# TODO: handle /MT and static lib
|
||||
# In Visual C++ naming convention each of these four kinds of Windows libraries has it's standard suffix:
|
||||
# * MD for dynamic-release
|
||||
# * MDd for dynamic-debug
|
||||
# * MT for static-release
|
||||
# * MTd for static-debug
|
||||
|
||||
# Implementation details:
|
||||
# We are using the libraries located in the VC subdir instead of the parent directory eventhough :
|
||||
# libeay32MD.lib is identical to ../libeay32.lib, and
|
||||
# ssleay32MD.lib is identical to ../ssleay32.lib
|
||||
find_library(LIB_EAY_DEBUG
|
||||
NAMES
|
||||
libeay32MDd
|
||||
libeay32d
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
||||
PATH_SUFFIXES
|
||||
"lib"
|
||||
"VC"
|
||||
"lib/VC"
|
||||
)
|
||||
|
||||
find_library(LIB_EAY_RELEASE
|
||||
NAMES
|
||||
libeay32MD
|
||||
libeay32
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
||||
PATH_SUFFIXES
|
||||
"lib"
|
||||
"VC"
|
||||
"lib/VC"
|
||||
)
|
||||
|
||||
find_library(SSL_EAY_DEBUG
|
||||
NAMES
|
||||
ssleay32MDd
|
||||
ssleay32d
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
||||
PATH_SUFFIXES
|
||||
"lib"
|
||||
"VC"
|
||||
"lib/VC"
|
||||
)
|
||||
|
||||
find_library(SSL_EAY_RELEASE
|
||||
NAMES
|
||||
ssleay32MD
|
||||
ssleay32
|
||||
ssl
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
||||
PATH_SUFFIXES
|
||||
"lib"
|
||||
"VC"
|
||||
"lib/VC"
|
||||
)
|
||||
|
||||
set(LIB_EAY_LIBRARY_DEBUG "${LIB_EAY_DEBUG}")
|
||||
set(LIB_EAY_LIBRARY_RELEASE "${LIB_EAY_RELEASE}")
|
||||
set(SSL_EAY_LIBRARY_DEBUG "${SSL_EAY_DEBUG}")
|
||||
set(SSL_EAY_LIBRARY_RELEASE "${SSL_EAY_RELEASE}")
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
|
||||
select_library_configurations(LIB_EAY)
|
||||
select_library_configurations(SSL_EAY)
|
||||
|
||||
mark_as_advanced(LIB_EAY_LIBRARY_DEBUG LIB_EAY_LIBRARY_RELEASE
|
||||
SSL_EAY_LIBRARY_DEBUG SSL_EAY_LIBRARY_RELEASE)
|
||||
set( OPENSSL_SSL_LIBRARY ${SSL_EAY_LIBRARY} )
|
||||
set( OPENSSL_CRYPTO_LIBRARY ${LIB_EAY_LIBRARY} )
|
||||
set( OPENSSL_LIBRARIES ${SSL_EAY_LIBRARY} ${LIB_EAY_LIBRARY} )
|
||||
elseif(MINGW)
|
||||
# same player, for MinGW
|
||||
set(LIB_EAY_NAMES libeay32)
|
||||
set(SSL_EAY_NAMES ssleay32)
|
||||
if(CMAKE_CROSSCOMPILING)
|
||||
list(APPEND LIB_EAY_NAMES crypto)
|
||||
list(APPEND SSL_EAY_NAMES ssl)
|
||||
endif()
|
||||
find_library(LIB_EAY
|
||||
NAMES
|
||||
${LIB_EAY_NAMES}
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
||||
PATH_SUFFIXES
|
||||
"lib"
|
||||
"lib/MinGW"
|
||||
)
|
||||
|
||||
find_library(SSL_EAY
|
||||
NAMES
|
||||
${SSL_EAY_NAMES}
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
||||
PATH_SUFFIXES
|
||||
"lib"
|
||||
"lib/MinGW"
|
||||
)
|
||||
|
||||
mark_as_advanced(SSL_EAY LIB_EAY)
|
||||
set( OPENSSL_SSL_LIBRARY ${SSL_EAY} )
|
||||
set( OPENSSL_CRYPTO_LIBRARY ${LIB_EAY} )
|
||||
set( OPENSSL_LIBRARIES ${SSL_EAY} ${LIB_EAY} )
|
||||
unset(LIB_EAY_NAMES)
|
||||
unset(SSL_EAY_NAMES)
|
||||
else()
|
||||
# Not sure what to pick for -say- intel, let's use the toplevel ones and hope someone report issues:
|
||||
find_library(LIB_EAY
|
||||
NAMES
|
||||
libeay32
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
||||
HINTS
|
||||
${_OPENSSL_LIBDIR}
|
||||
PATH_SUFFIXES
|
||||
lib
|
||||
)
|
||||
|
||||
find_library(SSL_EAY
|
||||
NAMES
|
||||
ssleay32
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
||||
HINTS
|
||||
${_OPENSSL_LIBDIR}
|
||||
PATH_SUFFIXES
|
||||
lib
|
||||
)
|
||||
|
||||
mark_as_advanced(SSL_EAY LIB_EAY)
|
||||
set( OPENSSL_SSL_LIBRARY ${SSL_EAY} )
|
||||
set( OPENSSL_CRYPTO_LIBRARY ${LIB_EAY} )
|
||||
set( OPENSSL_LIBRARIES ${SSL_EAY} ${LIB_EAY} )
|
||||
endif()
|
||||
else()
|
||||
|
||||
find_library(OPENSSL_SSL_LIBRARY
|
||||
NAMES
|
||||
ssl
|
||||
ssleay32
|
||||
ssleay32MD
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
||||
HINTS
|
||||
${_OPENSSL_LIBDIR}
|
||||
PATH_SUFFIXES
|
||||
lib
|
||||
)
|
||||
|
||||
find_library(OPENSSL_CRYPTO_LIBRARY
|
||||
NAMES
|
||||
crypto
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
||||
HINTS
|
||||
${_OPENSSL_LIBDIR}
|
||||
PATH_SUFFIXES
|
||||
lib
|
||||
)
|
||||
|
||||
mark_as_advanced(OPENSSL_CRYPTO_LIBRARY OPENSSL_SSL_LIBRARY)
|
||||
|
||||
# compat defines
|
||||
set(OPENSSL_SSL_LIBRARIES ${OPENSSL_SSL_LIBRARY})
|
||||
set(OPENSSL_CRYPTO_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||
|
||||
set(OPENSSL_LIBRARIES ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY})
|
||||
|
||||
endif()
|
||||
|
||||
function(from_hex HEX DEC)
|
||||
string(TOUPPER "${HEX}" HEX)
|
||||
set(_res 0)
|
||||
string(LENGTH "${HEX}" _strlen)
|
||||
|
||||
while (_strlen GREATER 0)
|
||||
math(EXPR _res "${_res} * 16")
|
||||
string(SUBSTRING "${HEX}" 0 1 NIBBLE)
|
||||
string(SUBSTRING "${HEX}" 1 -1 HEX)
|
||||
if (NIBBLE STREQUAL "A")
|
||||
math(EXPR _res "${_res} + 10")
|
||||
elseif (NIBBLE STREQUAL "B")
|
||||
math(EXPR _res "${_res} + 11")
|
||||
elseif (NIBBLE STREQUAL "C")
|
||||
math(EXPR _res "${_res} + 12")
|
||||
elseif (NIBBLE STREQUAL "D")
|
||||
math(EXPR _res "${_res} + 13")
|
||||
elseif (NIBBLE STREQUAL "E")
|
||||
math(EXPR _res "${_res} + 14")
|
||||
elseif (NIBBLE STREQUAL "F")
|
||||
math(EXPR _res "${_res} + 15")
|
||||
else()
|
||||
math(EXPR _res "${_res} + ${NIBBLE}")
|
||||
endif()
|
||||
|
||||
string(LENGTH "${HEX}" _strlen)
|
||||
endwhile()
|
||||
|
||||
set(${DEC} ${_res} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
if(OPENSSL_INCLUDE_DIR AND EXISTS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h")
|
||||
file(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h" openssl_version_str
|
||||
REGEX "^#[\t ]*define[\t ]+OPENSSL_VERSION_NUMBER[\t ]+0x([0-9a-fA-F])+.*")
|
||||
|
||||
if(openssl_version_str)
|
||||
# The version number is encoded as 0xMNNFFPPS: major minor fix patch status
|
||||
# The status gives if this is a developer or prerelease and is ignored here.
|
||||
# Major, minor, and fix directly translate into the version numbers shown in
|
||||
# the string. The patch field translates to the single character suffix that
|
||||
# indicates the bug fix state, which 00 -> nothing, 01 -> a, 02 -> b and so
|
||||
# on.
|
||||
|
||||
string(REGEX REPLACE "^.*OPENSSL_VERSION_NUMBER[\t ]+0x([0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F]).*$"
|
||||
"\\1;\\2;\\3;\\4;\\5" OPENSSL_VERSION_LIST "${openssl_version_str}")
|
||||
list(GET OPENSSL_VERSION_LIST 0 OPENSSL_VERSION_MAJOR)
|
||||
list(GET OPENSSL_VERSION_LIST 1 OPENSSL_VERSION_MINOR)
|
||||
from_hex("${OPENSSL_VERSION_MINOR}" OPENSSL_VERSION_MINOR)
|
||||
list(GET OPENSSL_VERSION_LIST 2 OPENSSL_VERSION_FIX)
|
||||
from_hex("${OPENSSL_VERSION_FIX}" OPENSSL_VERSION_FIX)
|
||||
list(GET OPENSSL_VERSION_LIST 3 OPENSSL_VERSION_PATCH)
|
||||
|
||||
if (NOT OPENSSL_VERSION_PATCH STREQUAL "00")
|
||||
from_hex("${OPENSSL_VERSION_PATCH}" _tmp)
|
||||
# 96 is the ASCII code of 'a' minus 1
|
||||
math(EXPR OPENSSL_VERSION_PATCH_ASCII "${_tmp} + 96")
|
||||
unset(_tmp)
|
||||
# Once anyone knows how OpenSSL would call the patch versions beyond 'z'
|
||||
# this should be updated to handle that, too. This has not happened yet
|
||||
# so it is simply ignored here for now.
|
||||
string(ASCII "${OPENSSL_VERSION_PATCH_ASCII}" OPENSSL_VERSION_PATCH_STRING)
|
||||
endif ()
|
||||
|
||||
set(OPENSSL_VERSION "${OPENSSL_VERSION_MAJOR}.${OPENSSL_VERSION_MINOR}.${OPENSSL_VERSION_FIX}${OPENSSL_VERSION_PATCH_STRING}")
|
||||
else ()
|
||||
# Since OpenSSL 3.0.0, the new version format is MAJOR.MINOR.PATCH and
|
||||
# a new OPENSSL_VERSION_STR macro contains exactly that
|
||||
file(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h" OPENSSL_VERSION_STR
|
||||
REGEX "^#[\t ]*define[\t ]+OPENSSL_VERSION_STR[\t ]+\"([0-9])+\\.([0-9])+\\.([0-9])+\".*")
|
||||
string(REGEX REPLACE "^.*OPENSSL_VERSION_STR[\t ]+\"([0-9]+\\.[0-9]+\\.[0-9]+)\".*$"
|
||||
"\\1" OPENSSL_VERSION_STR "${OPENSSL_VERSION_STR}")
|
||||
|
||||
set(OPENSSL_VERSION "${OPENSSL_VERSION_STR}")
|
||||
|
||||
# Setting OPENSSL_VERSION_MAJOR OPENSSL_VERSION_MINOR and OPENSSL_VERSION_FIX
|
||||
string(REGEX MATCHALL "([0-9])+" OPENSSL_VERSION_NUMBER "${OPENSSL_VERSION}")
|
||||
list(POP_FRONT OPENSSL_VERSION_NUMBER
|
||||
OPENSSL_VERSION_MAJOR
|
||||
OPENSSL_VERSION_MINOR
|
||||
OPENSSL_VERSION_FIX)
|
||||
|
||||
unset(OPENSSL_VERSION_NUMBER)
|
||||
unset(OPENSSL_VERSION_STR)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
|
||||
|
||||
if (OPENSSL_VERSION)
|
||||
find_package_handle_standard_args(OpenSSL
|
||||
REQUIRED_VARS
|
||||
OPENSSL_LIBRARIES
|
||||
OPENSSL_INCLUDE_DIR
|
||||
VERSION_VAR
|
||||
OPENSSL_VERSION
|
||||
FAIL_MESSAGE
|
||||
"Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR"
|
||||
)
|
||||
else ()
|
||||
find_package_handle_standard_args(OpenSSL "Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR"
|
||||
OPENSSL_LIBRARIES
|
||||
OPENSSL_INCLUDE_DIR
|
||||
)
|
||||
endif ()
|
||||
|
||||
mark_as_advanced(OPENSSL_INCLUDE_DIR OPENSSL_LIBRARIES)
|
||||
382
cmake/Modules/FindPackageHandleStandardArgs.cmake
Normal file
382
cmake/Modules/FindPackageHandleStandardArgs.cmake
Normal file
@@ -0,0 +1,382 @@
|
||||
#.rst:
|
||||
# FindPackageHandleStandardArgs
|
||||
# -----------------------------
|
||||
#
|
||||
#
|
||||
#
|
||||
# FIND_PACKAGE_HANDLE_STANDARD_ARGS(<name> ... )
|
||||
#
|
||||
# This function is intended to be used in FindXXX.cmake modules files.
|
||||
# It handles the REQUIRED, QUIET and version-related arguments to
|
||||
# find_package(). It also sets the <packagename>_FOUND variable. The
|
||||
# package is considered found if all variables <var1>... listed contain
|
||||
# valid results, e.g. valid filepaths.
|
||||
#
|
||||
# There are two modes of this function. The first argument in both
|
||||
# modes is the name of the Find-module where it is called (in original
|
||||
# casing).
|
||||
#
|
||||
# The first simple mode looks like this:
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# FIND_PACKAGE_HANDLE_STANDARD_ARGS(<name>
|
||||
# (DEFAULT_MSG|"Custom failure message") <var1>...<varN> )
|
||||
#
|
||||
# If the variables <var1> to <varN> are all valid, then
|
||||
# <UPPERCASED_NAME>_FOUND will be set to TRUE. If DEFAULT_MSG is given
|
||||
# as second argument, then the function will generate itself useful
|
||||
# success and error messages. You can also supply a custom error
|
||||
# message for the failure case. This is not recommended.
|
||||
#
|
||||
# The second mode is more powerful and also supports version checking:
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# FIND_PACKAGE_HANDLE_STANDARD_ARGS(<NAME>
|
||||
# [FOUND_VAR <resultVar>]
|
||||
# [REQUIRED_VARS <var1>...<varN>]
|
||||
# [VERSION_VAR <versionvar>]
|
||||
# [HANDLE_COMPONENTS]
|
||||
# [CONFIG_MODE]
|
||||
# [FAIL_MESSAGE "Custom failure message"] )
|
||||
#
|
||||
# In this mode, the name of the result-variable can be set either to
|
||||
# either <UPPERCASED_NAME>_FOUND or <OriginalCase_Name>_FOUND using the
|
||||
# FOUND_VAR option. Other names for the result-variable are not
|
||||
# allowed. So for a Find-module named FindFooBar.cmake, the two
|
||||
# possible names are FooBar_FOUND and FOOBAR_FOUND. It is recommended
|
||||
# to use the original case version. If the FOUND_VAR option is not
|
||||
# used, the default is <UPPERCASED_NAME>_FOUND.
|
||||
#
|
||||
# As in the simple mode, if <var1> through <varN> are all valid,
|
||||
# <packagename>_FOUND will be set to TRUE. After REQUIRED_VARS the
|
||||
# variables which are required for this package are listed. Following
|
||||
# VERSION_VAR the name of the variable can be specified which holds the
|
||||
# version of the package which has been found. If this is done, this
|
||||
# version will be checked against the (potentially) specified required
|
||||
# version used in the find_package() call. The EXACT keyword is also
|
||||
# handled. The default messages include information about the required
|
||||
# version and the version which has been actually found, both if the
|
||||
# version is ok or not. If the package supports components, use the
|
||||
# HANDLE_COMPONENTS option to enable handling them. In this case,
|
||||
# find_package_handle_standard_args() will report which components have
|
||||
# been found and which are missing, and the <packagename>_FOUND variable
|
||||
# will be set to FALSE if any of the required components (i.e. not the
|
||||
# ones listed after OPTIONAL_COMPONENTS) are missing. Use the option
|
||||
# CONFIG_MODE if your FindXXX.cmake module is a wrapper for a
|
||||
# find_package(... NO_MODULE) call. In this case VERSION_VAR will be
|
||||
# set to <NAME>_VERSION and the macro will automatically check whether
|
||||
# the Config module was found. Via FAIL_MESSAGE a custom failure
|
||||
# message can be specified, if this is not used, the default message
|
||||
# will be displayed.
|
||||
#
|
||||
# Example for mode 1:
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# find_package_handle_standard_args(LibXml2 DEFAULT_MSG
|
||||
# LIBXML2_LIBRARY LIBXML2_INCLUDE_DIR)
|
||||
#
|
||||
#
|
||||
#
|
||||
# LibXml2 is considered to be found, if both LIBXML2_LIBRARY and
|
||||
# LIBXML2_INCLUDE_DIR are valid. Then also LIBXML2_FOUND is set to
|
||||
# TRUE. If it is not found and REQUIRED was used, it fails with
|
||||
# FATAL_ERROR, independent whether QUIET was used or not. If it is
|
||||
# found, success will be reported, including the content of <var1>. On
|
||||
# repeated Cmake runs, the same message won't be printed again.
|
||||
#
|
||||
# Example for mode 2:
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# find_package_handle_standard_args(LibXslt
|
||||
# FOUND_VAR LibXslt_FOUND
|
||||
# REQUIRED_VARS LibXslt_LIBRARIES LibXslt_INCLUDE_DIRS
|
||||
# VERSION_VAR LibXslt_VERSION_STRING)
|
||||
#
|
||||
# In this case, LibXslt is considered to be found if the variable(s)
|
||||
# listed after REQUIRED_VAR are all valid, i.e. LibXslt_LIBRARIES and
|
||||
# LibXslt_INCLUDE_DIRS in this case. The result will then be stored in
|
||||
# LibXslt_FOUND . Also the version of LibXslt will be checked by using
|
||||
# the version contained in LibXslt_VERSION_STRING. Since no
|
||||
# FAIL_MESSAGE is given, the default messages will be printed.
|
||||
#
|
||||
# Another example for mode 2:
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# find_package(Automoc4 QUIET NO_MODULE HINTS /opt/automoc4)
|
||||
# find_package_handle_standard_args(Automoc4 CONFIG_MODE)
|
||||
#
|
||||
# In this case, FindAutmoc4.cmake wraps a call to find_package(Automoc4
|
||||
# NO_MODULE) and adds an additional search directory for automoc4. Here
|
||||
# the result will be stored in AUTOMOC4_FOUND. The following
|
||||
# FIND_PACKAGE_HANDLE_STANDARD_ARGS() call produces a proper
|
||||
# success/error message.
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2007-2009 Kitware, Inc.
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
# (To distribute this file outside of CMake, substitute the full
|
||||
# License text for the above reference.)
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageMessage.cmake)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/CMakeParseArguments.cmake)
|
||||
|
||||
# internal helper macro
|
||||
macro(_FPHSA_FAILURE_MESSAGE _msg)
|
||||
if (${_NAME}_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "${_msg}")
|
||||
else ()
|
||||
if (NOT ${_NAME}_FIND_QUIETLY)
|
||||
message(STATUS "${_msg}")
|
||||
endif ()
|
||||
endif ()
|
||||
endmacro()
|
||||
|
||||
|
||||
# internal helper macro to generate the failure message when used in CONFIG_MODE:
|
||||
macro(_FPHSA_HANDLE_FAILURE_CONFIG_MODE)
|
||||
# <name>_CONFIG is set, but FOUND is false, this means that some other of the REQUIRED_VARS was not found:
|
||||
if(${_NAME}_CONFIG)
|
||||
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: missing: ${MISSING_VARS} (found ${${_NAME}_CONFIG} ${VERSION_MSG})")
|
||||
else()
|
||||
# If _CONSIDERED_CONFIGS is set, the config-file has been found, but no suitable version.
|
||||
# List them all in the error message:
|
||||
if(${_NAME}_CONSIDERED_CONFIGS)
|
||||
set(configsText "")
|
||||
list(LENGTH ${_NAME}_CONSIDERED_CONFIGS configsCount)
|
||||
math(EXPR configsCount "${configsCount} - 1")
|
||||
foreach(currentConfigIndex RANGE ${configsCount})
|
||||
list(GET ${_NAME}_CONSIDERED_CONFIGS ${currentConfigIndex} filename)
|
||||
list(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version)
|
||||
set(configsText "${configsText} ${filename} (version ${version})\n")
|
||||
endforeach()
|
||||
if (${_NAME}_NOT_FOUND_MESSAGE)
|
||||
set(configsText "${configsText} Reason given by package: ${${_NAME}_NOT_FOUND_MESSAGE}\n")
|
||||
endif()
|
||||
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:\n${configsText}")
|
||||
|
||||
else()
|
||||
# Simple case: No Config-file was found at all:
|
||||
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: found neither ${_NAME}Config.cmake nor ${_NAME_LOWER}-config.cmake ${VERSION_MSG}")
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
|
||||
function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)
|
||||
|
||||
# set up the arguments for CMAKE_PARSE_ARGUMENTS and check whether we are in
|
||||
# new extended or in the "old" mode:
|
||||
set(options CONFIG_MODE HANDLE_COMPONENTS)
|
||||
set(oneValueArgs FAIL_MESSAGE VERSION_VAR FOUND_VAR)
|
||||
set(multiValueArgs REQUIRED_VARS)
|
||||
set(_KEYWORDS_FOR_EXTENDED_MODE ${options} ${oneValueArgs} ${multiValueArgs} )
|
||||
list(FIND _KEYWORDS_FOR_EXTENDED_MODE "${_FIRST_ARG}" INDEX)
|
||||
|
||||
if(${INDEX} EQUAL -1)
|
||||
set(FPHSA_FAIL_MESSAGE ${_FIRST_ARG})
|
||||
set(FPHSA_REQUIRED_VARS ${ARGN})
|
||||
set(FPHSA_VERSION_VAR)
|
||||
else()
|
||||
|
||||
CMAKE_PARSE_ARGUMENTS(FPHSA "${options}" "${oneValueArgs}" "${multiValueArgs}" ${_FIRST_ARG} ${ARGN})
|
||||
|
||||
if(FPHSA_UNPARSED_ARGUMENTS)
|
||||
message(FATAL_ERROR "Unknown keywords given to FIND_PACKAGE_HANDLE_STANDARD_ARGS(): \"${FPHSA_UNPARSED_ARGUMENTS}\"")
|
||||
endif()
|
||||
|
||||
if(NOT FPHSA_FAIL_MESSAGE)
|
||||
set(FPHSA_FAIL_MESSAGE "DEFAULT_MSG")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# now that we collected all arguments, process them
|
||||
|
||||
if("x${FPHSA_FAIL_MESSAGE}" STREQUAL "xDEFAULT_MSG")
|
||||
set(FPHSA_FAIL_MESSAGE "Could NOT find ${_NAME}")
|
||||
endif()
|
||||
|
||||
# In config-mode, we rely on the variable <package>_CONFIG, which is set by find_package()
|
||||
# when it successfully found the config-file, including version checking:
|
||||
if(FPHSA_CONFIG_MODE)
|
||||
list(INSERT FPHSA_REQUIRED_VARS 0 ${_NAME}_CONFIG)
|
||||
list(REMOVE_DUPLICATES FPHSA_REQUIRED_VARS)
|
||||
set(FPHSA_VERSION_VAR ${_NAME}_VERSION)
|
||||
endif()
|
||||
|
||||
if(NOT FPHSA_REQUIRED_VARS)
|
||||
message(FATAL_ERROR "No REQUIRED_VARS specified for FIND_PACKAGE_HANDLE_STANDARD_ARGS()")
|
||||
endif()
|
||||
|
||||
list(GET FPHSA_REQUIRED_VARS 0 _FIRST_REQUIRED_VAR)
|
||||
|
||||
string(TOUPPER ${_NAME} _NAME_UPPER)
|
||||
string(TOLOWER ${_NAME} _NAME_LOWER)
|
||||
|
||||
if(FPHSA_FOUND_VAR)
|
||||
if(FPHSA_FOUND_VAR MATCHES "^${_NAME}_FOUND$" OR FPHSA_FOUND_VAR MATCHES "^${_NAME_UPPER}_FOUND$")
|
||||
set(_FOUND_VAR ${FPHSA_FOUND_VAR})
|
||||
else()
|
||||
message(FATAL_ERROR "The argument for FOUND_VAR is \"${FPHSA_FOUND_VAR}\", but only \"${_NAME}_FOUND\" and \"${_NAME_UPPER}_FOUND\" are valid names.")
|
||||
endif()
|
||||
else()
|
||||
set(_FOUND_VAR ${_NAME_UPPER}_FOUND)
|
||||
endif()
|
||||
|
||||
# collect all variables which were not found, so they can be printed, so the
|
||||
# user knows better what went wrong (#6375)
|
||||
set(MISSING_VARS "")
|
||||
set(DETAILS "")
|
||||
# check if all passed variables are valid
|
||||
unset(${_FOUND_VAR})
|
||||
foreach(_CURRENT_VAR ${FPHSA_REQUIRED_VARS})
|
||||
if(NOT ${_CURRENT_VAR})
|
||||
set(${_FOUND_VAR} FALSE)
|
||||
set(MISSING_VARS "${MISSING_VARS} ${_CURRENT_VAR}")
|
||||
else()
|
||||
set(DETAILS "${DETAILS}[${${_CURRENT_VAR}}]")
|
||||
endif()
|
||||
endforeach()
|
||||
if(NOT "${${_FOUND_VAR}}" STREQUAL "FALSE")
|
||||
set(${_FOUND_VAR} TRUE)
|
||||
endif()
|
||||
|
||||
# component handling
|
||||
unset(FOUND_COMPONENTS_MSG)
|
||||
unset(MISSING_COMPONENTS_MSG)
|
||||
|
||||
if(FPHSA_HANDLE_COMPONENTS)
|
||||
foreach(comp ${${_NAME}_FIND_COMPONENTS})
|
||||
if(${_NAME}_${comp}_FOUND)
|
||||
|
||||
if(NOT DEFINED FOUND_COMPONENTS_MSG)
|
||||
set(FOUND_COMPONENTS_MSG "found components: ")
|
||||
endif()
|
||||
set(FOUND_COMPONENTS_MSG "${FOUND_COMPONENTS_MSG} ${comp}")
|
||||
|
||||
else()
|
||||
|
||||
if(NOT DEFINED MISSING_COMPONENTS_MSG)
|
||||
set(MISSING_COMPONENTS_MSG "missing components: ")
|
||||
endif()
|
||||
set(MISSING_COMPONENTS_MSG "${MISSING_COMPONENTS_MSG} ${comp}")
|
||||
|
||||
if(${_NAME}_FIND_REQUIRED_${comp})
|
||||
set(${_FOUND_VAR} FALSE)
|
||||
set(MISSING_VARS "${MISSING_VARS} ${comp}")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
endforeach()
|
||||
set(COMPONENT_MSG "${FOUND_COMPONENTS_MSG} ${MISSING_COMPONENTS_MSG}")
|
||||
set(DETAILS "${DETAILS}[c${COMPONENT_MSG}]")
|
||||
endif()
|
||||
|
||||
# version handling:
|
||||
set(VERSION_MSG "")
|
||||
set(VERSION_OK TRUE)
|
||||
set(VERSION ${${FPHSA_VERSION_VAR}})
|
||||
|
||||
# check with DEFINED here as the requested or found version may be "0"
|
||||
if (DEFINED ${_NAME}_FIND_VERSION)
|
||||
if(DEFINED ${FPHSA_VERSION_VAR})
|
||||
|
||||
if(${_NAME}_FIND_VERSION_EXACT) # exact version required
|
||||
# count the dots in the version string
|
||||
string(REGEX REPLACE "[^.]" "" _VERSION_DOTS "${VERSION}")
|
||||
# add one dot because there is one dot more than there are components
|
||||
string(LENGTH "${_VERSION_DOTS}." _VERSION_DOTS)
|
||||
if (_VERSION_DOTS GREATER ${_NAME}_FIND_VERSION_COUNT)
|
||||
# Because of the C++ implementation of find_package() ${_NAME}_FIND_VERSION_COUNT
|
||||
# is at most 4 here. Therefore a simple lookup table is used.
|
||||
if (${_NAME}_FIND_VERSION_COUNT EQUAL 1)
|
||||
set(_VERSION_REGEX "[^.]*")
|
||||
elseif (${_NAME}_FIND_VERSION_COUNT EQUAL 2)
|
||||
set(_VERSION_REGEX "[^.]*\\.[^.]*")
|
||||
elseif (${_NAME}_FIND_VERSION_COUNT EQUAL 3)
|
||||
set(_VERSION_REGEX "[^.]*\\.[^.]*\\.[^.]*")
|
||||
else ()
|
||||
set(_VERSION_REGEX "[^.]*\\.[^.]*\\.[^.]*\\.[^.]*")
|
||||
endif ()
|
||||
string(REGEX REPLACE "^(${_VERSION_REGEX})\\..*" "\\1" _VERSION_HEAD "${VERSION}")
|
||||
unset(_VERSION_REGEX)
|
||||
if (NOT ${_NAME}_FIND_VERSION VERSION_EQUAL _VERSION_HEAD)
|
||||
set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"")
|
||||
set(VERSION_OK FALSE)
|
||||
else ()
|
||||
set(VERSION_MSG "(found suitable exact version \"${VERSION}\")")
|
||||
endif ()
|
||||
unset(_VERSION_HEAD)
|
||||
else ()
|
||||
if (NOT ${_NAME}_FIND_VERSION VERSION_EQUAL VERSION)
|
||||
set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"")
|
||||
set(VERSION_OK FALSE)
|
||||
else ()
|
||||
set(VERSION_MSG "(found suitable exact version \"${VERSION}\")")
|
||||
endif ()
|
||||
endif ()
|
||||
unset(_VERSION_DOTS)
|
||||
|
||||
else() # minimum version specified:
|
||||
if (${_NAME}_FIND_VERSION VERSION_GREATER VERSION)
|
||||
set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is at least \"${${_NAME}_FIND_VERSION}\"")
|
||||
set(VERSION_OK FALSE)
|
||||
else ()
|
||||
set(VERSION_MSG "(found suitable version \"${VERSION}\", minimum required is \"${${_NAME}_FIND_VERSION}\")")
|
||||
endif ()
|
||||
endif()
|
||||
|
||||
else()
|
||||
|
||||
# if the package was not found, but a version was given, add that to the output:
|
||||
if(${_NAME}_FIND_VERSION_EXACT)
|
||||
set(VERSION_MSG "(Required is exact version \"${${_NAME}_FIND_VERSION}\")")
|
||||
else()
|
||||
set(VERSION_MSG "(Required is at least version \"${${_NAME}_FIND_VERSION}\")")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
else ()
|
||||
if(VERSION)
|
||||
set(VERSION_MSG "(found version \"${VERSION}\")")
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
if(VERSION_OK)
|
||||
set(DETAILS "${DETAILS}[v${VERSION}(${${_NAME}_FIND_VERSION})]")
|
||||
else()
|
||||
set(${_FOUND_VAR} FALSE)
|
||||
endif()
|
||||
|
||||
|
||||
# print the result:
|
||||
if (${_FOUND_VAR})
|
||||
FIND_PACKAGE_MESSAGE(${_NAME} "Found ${_NAME}: ${${_FIRST_REQUIRED_VAR}} ${VERSION_MSG} ${COMPONENT_MSG}" "${DETAILS}")
|
||||
else ()
|
||||
|
||||
if(FPHSA_CONFIG_MODE)
|
||||
_FPHSA_HANDLE_FAILURE_CONFIG_MODE()
|
||||
else()
|
||||
if(NOT VERSION_OK)
|
||||
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: ${VERSION_MSG} (found ${${_FIRST_REQUIRED_VAR}})")
|
||||
else()
|
||||
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} (missing: ${MISSING_VARS}) ${VERSION_MSG}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
endif ()
|
||||
|
||||
set(${_FOUND_VAR} ${${_FOUND_VAR}} PARENT_SCOPE)
|
||||
|
||||
endfunction()
|
||||
57
cmake/Modules/FindPackageMessage.cmake
Normal file
57
cmake/Modules/FindPackageMessage.cmake
Normal file
@@ -0,0 +1,57 @@
|
||||
#.rst:
|
||||
# FindPackageMessage
|
||||
# ------------------
|
||||
#
|
||||
#
|
||||
#
|
||||
# FIND_PACKAGE_MESSAGE(<name> "message for user" "find result details")
|
||||
#
|
||||
# This macro is intended to be used in FindXXX.cmake modules files. It
|
||||
# will print a message once for each unique find result. This is useful
|
||||
# for telling the user where a package was found. The first argument
|
||||
# specifies the name (XXX) of the package. The second argument
|
||||
# specifies the message to display. The third argument lists details
|
||||
# about the find result so that if they change the message will be
|
||||
# displayed again. The macro also obeys the QUIET argument to the
|
||||
# find_package command.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# if(X11_FOUND)
|
||||
# FIND_PACKAGE_MESSAGE(X11 "Found X11: ${X11_X11_LIB}"
|
||||
# "[${X11_X11_LIB}][${X11_INCLUDE_DIR}]")
|
||||
# else()
|
||||
# ...
|
||||
# endif()
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2008-2009 Kitware, Inc.
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
# (To distribute this file outside of CMake, substitute the full
|
||||
# License text for the above reference.)
|
||||
|
||||
function(FIND_PACKAGE_MESSAGE pkg msg details)
|
||||
# Avoid printing a message repeatedly for the same find result.
|
||||
if(NOT ${pkg}_FIND_QUIETLY)
|
||||
string(REPLACE "\n" "" details "${details}")
|
||||
set(DETAILS_VAR FIND_PACKAGE_MESSAGE_DETAILS_${pkg})
|
||||
if(NOT "${details}" STREQUAL "${${DETAILS_VAR}}")
|
||||
# The message has not yet been printed.
|
||||
message(STATUS "${msg}")
|
||||
|
||||
# Save the find details in the cache to avoid printing the same
|
||||
# message again.
|
||||
set("${DETAILS_VAR}" "${details}"
|
||||
CACHE INTERNAL "Details about finding ${pkg}")
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
118
colab/xfrpc.ipynb
Normal file
118
colab/xfrpc.ipynb
Normal file
@@ -0,0 +1,118 @@
|
||||
{
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"provenance": [],
|
||||
"authorship_tag": "ABX9TyNuWIELWWDtoNBAYOHZfXRi",
|
||||
"include_colab_link": true
|
||||
},
|
||||
"kernelspec": {
|
||||
"name": "python3",
|
||||
"display_name": "Python 3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "view-in-github",
|
||||
"colab_type": "text"
|
||||
},
|
||||
"source": [
|
||||
"<a href=\"https://colab.research.google.com/github/liudf0716/xfrpc/blob/master/colab_xfrpc.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "ErrkZjxXvVNe"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!git clone https://github.com/liudf0716/xfrpc.git\n",
|
||||
"! cd xfrpc/ && mkdir build && cd build && cmake .. && make && cp xfrpc /usr/bin/"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"! pip install configparser\n",
|
||||
"\n",
|
||||
"import configparser\n",
|
||||
"import sys\n",
|
||||
"\n",
|
||||
"server_addr = \"colab.xfrpc.xyz\" #@param {type:\"string\"}\n",
|
||||
"token = \"l00JJ6ea302lT\" #@param {type:\"string\"}\n",
|
||||
"server_port = 8443 #@param {type:\"integer\"}\n",
|
||||
"remote_port = 6003 #@param {type:\"integer\"}\n",
|
||||
"plugin_user = \"xfrpc\" #@param {type:\"string\"}\n",
|
||||
"plugin_pwd = \"123456\" #@param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"def get_input(prompt):\n",
|
||||
" \"\"\"Gets input from the user.\"\"\"\n",
|
||||
" return input(prompt)\n",
|
||||
"\n",
|
||||
"def generate_ini(server_addr, server_port, token, remote_port, user, pwd):\n",
|
||||
" \"\"\"Generates an INI file.\"\"\"\n",
|
||||
" config = configparser.ConfigParser()\n",
|
||||
"\n",
|
||||
" config[\"common\"] = {\n",
|
||||
" \"server_addr\": server_addr,\n",
|
||||
" \"server_port\": server_port,\n",
|
||||
" \"token\": token,\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" config[\"telnetd\"] = {\n",
|
||||
" \"type\": \"tcp\",\n",
|
||||
" \"remote_port\": remote_port,\n",
|
||||
" \"plugin\": \"telnetd\",\n",
|
||||
" \"plugin_user\": user,\n",
|
||||
" \"plugin_pwd\": pwd,\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" with open(\"my.ini\", \"w\") as f:\n",
|
||||
" config.write(f)\n",
|
||||
"\n",
|
||||
" print(\"Ini file generated successfully!\")\n",
|
||||
"\n",
|
||||
"if __name__ == \"__main__\":\n",
|
||||
" generate_ini(server_addr, server_port, token, remote_port, plugin_user, plugin_pwd)\n",
|
||||
"\n"
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "V7n8azihcBUl",
|
||||
"outputId": "b7d475f9-49af-4546-8381-b96a577258cb"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"Requirement already satisfied: configparser in /usr/local/lib/python3.10/dist-packages (6.0.0)\n",
|
||||
"Ini file generated successfully!\n"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"! xfrpc -c my.ini -f -d 6"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "KFLJaznZvrLG"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <syslog.h>
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
@@ -38,6 +39,7 @@
|
||||
#include "commandline.h"
|
||||
#include "debug.h"
|
||||
#include "version.h"
|
||||
#include "utils.h"
|
||||
|
||||
typedef void signal_func (int);
|
||||
|
||||
@@ -108,7 +110,7 @@ get_daemon_status()
|
||||
/** @internal
|
||||
* @brief Print usage
|
||||
*
|
||||
* Prints usage, called when wifidog is run with -h or with an unknown option
|
||||
* Prints usage, called when xfrpc is run with -h or with an unknown option
|
||||
*/
|
||||
static void
|
||||
usage(const char *appname)
|
||||
@@ -121,6 +123,7 @@ usage(const char *appname)
|
||||
fprintf(stdout, " -d <level> Debug level\n");
|
||||
fprintf(stdout, " -h Print usage\n");
|
||||
fprintf(stdout, " -v Print version information\n");
|
||||
fprintf(stdout, " -r Print run id of client\n");
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
@@ -133,7 +136,7 @@ parse_commandline(int argc, char **argv)
|
||||
int c;
|
||||
int flag = 0;
|
||||
|
||||
while (-1 != (c = getopt(argc, argv, "c:hfd:sw:vx:i:a:"))) {
|
||||
while (-1 != (c = getopt(argc, argv, "c:hfd:sw:vrx:i:a:"))) {
|
||||
|
||||
|
||||
switch (c) {
|
||||
@@ -146,9 +149,7 @@ parse_commandline(int argc, char **argv)
|
||||
case 'c':
|
||||
if (optarg) {
|
||||
confile = strdup(optarg); //never free it
|
||||
if (! confile)
|
||||
exit(0);
|
||||
|
||||
assert(confile);
|
||||
flag = 1;
|
||||
}
|
||||
break;
|
||||
@@ -165,10 +166,28 @@ parse_commandline(int argc, char **argv)
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
fprintf(stdout, "This is %s version " VERSION "\n", argv[0]);
|
||||
fprintf(stdout, "version: " VERSION "\n");
|
||||
exit(1);
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
{
|
||||
char ifname[16] = {0};
|
||||
if(get_net_ifname(ifname, 16)){
|
||||
debug(LOG_ERR, "error: get device sign ifname failed!");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
char if_mac[64] = {0};
|
||||
if(get_net_mac(ifname, if_mac, sizeof(if_mac))) {
|
||||
debug(LOG_ERR, "error: Hard ware MAC address of [%s] get failed!", ifname);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
fprintf(stdout, "run ID:%s\n", if_mac);
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
|
||||
26
common.c
26
common.c
@@ -1,3 +1,29 @@
|
||||
/* vim: set et ts=4 sts=4 sw=4 : */
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, contact: *
|
||||
* *
|
||||
* Free Software Foundation Voice: +1-617-542-5942 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
/** @file common.c
|
||||
@brief xfrp common function implemented
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
#include "uthash.h"
|
||||
#include "common.h"
|
||||
|
||||
|
||||
42
common.h
42
common.h
@@ -1,3 +1,29 @@
|
||||
/* vim: set et ts=4 sts=4 sw=4 : */
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, contact: *
|
||||
* *
|
||||
* Free Software Foundation Voice: +1-617-542-5942 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
/** @file common.h
|
||||
@brief xfrp common header
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
#ifndef _COMMON_H_
|
||||
#define _COMMON_H_
|
||||
|
||||
@@ -6,10 +32,20 @@
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <event2/bufferevent.h>
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/listener.h>
|
||||
#include <event2/util.h>
|
||||
#include <event2/event.h>
|
||||
#include <event2/dns.h>
|
||||
#include <event2/event_struct.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "uthash.h"
|
||||
|
||||
// #define BIGENDIAN_64BIT 0
|
||||
#define BIGENDIAN_32BIT 1
|
||||
#define BIGENDIAN_64BIT 1
|
||||
//#define BIGENDIAN_32BIT 1
|
||||
|
||||
#define SAFE_FREE(m) \
|
||||
if (m) free(m)
|
||||
@@ -37,4 +73,4 @@ uint64_t hton64(const uint64_t input);
|
||||
|
||||
typedef unsigned short ushort;
|
||||
|
||||
#endif //_COMMON_H_
|
||||
#endif //_COMMON_H_
|
||||
|
||||
455
config.c
455
config.c
@@ -20,17 +20,19 @@
|
||||
\********************************************************************/
|
||||
|
||||
/** @file config.c
|
||||
@brief xfrp client config related
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liudengfeng@kunteng.org>
|
||||
@brief xfrpc client config related
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <syslog.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include <shadow.h>
|
||||
#include <crypt.h>
|
||||
|
||||
#include "ini.h"
|
||||
#include "uthash.h"
|
||||
@@ -38,54 +40,42 @@
|
||||
#include "client.h"
|
||||
#include "debug.h"
|
||||
#include "msg.h"
|
||||
#include "utils.h"
|
||||
#include "version.h"
|
||||
|
||||
|
||||
// define a list of type in array
|
||||
static const char *valid_types[] = {
|
||||
"tcp",
|
||||
"udp",
|
||||
"socks5",
|
||||
"http",
|
||||
"https",
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct common_conf *c_conf;
|
||||
static struct proxy_client *p_clients;
|
||||
static struct proxy_service *p_services;
|
||||
static struct proxy_service *all_ps;
|
||||
|
||||
static void new_ftp_data_proxy_service(struct proxy_service *ftp_ps);
|
||||
|
||||
struct common_conf *get_common_config()
|
||||
struct common_conf *
|
||||
get_common_config()
|
||||
{
|
||||
return c_conf;
|
||||
};
|
||||
|
||||
void free_common_config()
|
||||
void
|
||||
free_common_config()
|
||||
{
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
|
||||
if (c_conf->server_addr) free(c_conf->server_addr);
|
||||
if (c_conf->http_proxy) free(c_conf->http_proxy);
|
||||
if (c_conf->log_file) free(c_conf->log_file);
|
||||
if (c_conf->log_way) free(c_conf->log_way);
|
||||
if (c_conf->log_level) free(c_conf->log_level);
|
||||
if (c_conf->auth_token) free(c_conf->auth_token);
|
||||
if (c_conf->privilege_token) free(c_conf->privilege_token);
|
||||
};
|
||||
|
||||
void free_base_config(struct base_conf *bconf)
|
||||
{
|
||||
if (bconf->name) free(bconf->name);
|
||||
if (bconf->auth_token) free(bconf->auth_token);
|
||||
if (bconf->type) free(bconf->type);
|
||||
if (bconf->privilege_token) free(bconf->privilege_token);
|
||||
if (bconf->host_header_rewrite) free(bconf->host_header_rewrite);
|
||||
if (bconf->http_username) free(bconf->http_username);
|
||||
if (bconf->http_password) free(bconf->http_password);
|
||||
if (bconf->subdomain) free(bconf->subdomain);
|
||||
}
|
||||
|
||||
struct proxy_client *get_all_pc()
|
||||
{
|
||||
return p_clients;
|
||||
}
|
||||
|
||||
struct proxy_service *get_all_proxy_services()
|
||||
{
|
||||
return p_services;
|
||||
}
|
||||
|
||||
static int is_true(const char *val)
|
||||
static int
|
||||
is_true(const char *val)
|
||||
{
|
||||
if (val && (strcmp(val, "true") == 0 || strcmp(val, "1") == 0))
|
||||
return 1;
|
||||
@@ -93,81 +83,100 @@ static int is_true(const char *val)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *get_valid_type(const char *val)
|
||||
static const char *
|
||||
get_valid_type(const char *val)
|
||||
{
|
||||
if (!val)
|
||||
return NULL;
|
||||
|
||||
#define MATCH_VALUE(s) strcmp(val, s) == 0
|
||||
if (MATCH_VALUE("tcp") ||
|
||||
MATCH_VALUE("http") ||
|
||||
MATCH_VALUE("https") ||
|
||||
MATCH_VALUE("udp")) { // will add ftp support in here
|
||||
|
||||
return val;
|
||||
// iterate the valid_types array
|
||||
for (int i = 0; valid_types[i]; i++) {
|
||||
if (MATCH_VALUE(valid_types[i])) {
|
||||
return valid_types[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void dump_common_conf()
|
||||
static void
|
||||
dump_common_conf()
|
||||
{
|
||||
if(!c_conf) {
|
||||
if(! c_conf) {
|
||||
debug(LOG_ERR, "Error: c_conf is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
debug(LOG_DEBUG, "Section[common]: {server_addr:%s, server_port:%d, auth_token:%s, privilege_token:%s, interval:%d, timeout:%d}",
|
||||
c_conf->server_addr, c_conf->server_port, c_conf->auth_token, c_conf->privilege_token, c_conf->heartbeat_interval, c_conf->heartbeat_timeout);
|
||||
debug(LOG_DEBUG, "Section[common]: {server_addr:%s, server_port:%d, auth_token:%s, interval:%d, timeout:%d}",
|
||||
c_conf->server_addr, c_conf->server_port, c_conf->auth_token,
|
||||
c_conf->heartbeat_interval, c_conf->heartbeat_timeout);
|
||||
}
|
||||
|
||||
static void dump_proxy_service(const int index, struct proxy_service *ps)
|
||||
static void
|
||||
dump_proxy_service(const int index, struct proxy_service *ps)
|
||||
{
|
||||
if (!ps)
|
||||
return;
|
||||
|
||||
if (0 > ps->local_port) {
|
||||
debug(LOG_ERR, "Proxy [%s] error: local_port not found", ps->proxy_name);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (NULL == ps->proxy_type) {
|
||||
ps->proxy_type = strdup("tcp");
|
||||
assert(ps->proxy_type);
|
||||
} else if (strcmp(ps->proxy_type, "ftp") == 0) {
|
||||
new_ftp_data_proxy_service(ps);
|
||||
}
|
||||
|
||||
if (!validate_proxy(ps)) {
|
||||
debug(LOG_ERR, "Error: validate_proxy failed");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
debug(LOG_DEBUG,
|
||||
"Proxy service %d: {name:%s, local_port:%d, type:%s}",
|
||||
index,
|
||||
ps->proxy_name,
|
||||
ps->local_port,
|
||||
ps->proxy_type);
|
||||
"Proxy service %d: {name:%s, local_port:%d, type:%s, use_encryption:%d, use_compression:%d, custom_domains:%s, subdomain:%s, locations:%s, host_header_rewrite:%s, http_user:%s, http_pwd:%s}",
|
||||
index,
|
||||
ps->proxy_name,
|
||||
ps->local_port,
|
||||
ps->proxy_type,
|
||||
ps->use_encryption,
|
||||
ps->use_compression,
|
||||
ps->custom_domains,
|
||||
ps->subdomain,
|
||||
ps->locations,
|
||||
ps->host_header_rewrite,
|
||||
ps->http_user,
|
||||
ps->http_pwd);
|
||||
}
|
||||
|
||||
static void dump_all_ps()
|
||||
static void
|
||||
dump_all_ps()
|
||||
{
|
||||
struct proxy_service *ps = NULL, *tmp = NULL;
|
||||
|
||||
int index = 0;
|
||||
HASH_ITER(hh, p_services, ps, tmp) {
|
||||
HASH_ITER(hh, all_ps, ps, tmp) {
|
||||
dump_proxy_service(index++, ps);
|
||||
}
|
||||
}
|
||||
|
||||
static struct proxy_service *new_proxy_service(const char *name)
|
||||
static struct proxy_service *
|
||||
new_proxy_service(const char *name)
|
||||
{
|
||||
if (! name)
|
||||
return NULL;
|
||||
struct proxy_service *ps = calloc(sizeof(struct proxy_service), 1);
|
||||
|
||||
struct proxy_service *ps = (struct proxy_service *)calloc(sizeof(struct proxy_service), 1);
|
||||
assert(ps);
|
||||
assert(c_conf);
|
||||
|
||||
ps->proxy_name = strdup(name);
|
||||
ps->ftp_cfg_proxy_name = NULL;
|
||||
assert(ps->proxy_name);
|
||||
|
||||
ps->proxy_type = NULL;
|
||||
ps->use_encryption = 0;
|
||||
ps->local_port = -1;
|
||||
ps->remote_port = -1;
|
||||
ps->local_port = 0;
|
||||
ps->remote_port = 0;
|
||||
ps->remote_data_port = 0;
|
||||
ps->use_compression = 0;
|
||||
ps->use_encryption = 0;
|
||||
|
||||
@@ -178,33 +187,198 @@ static struct proxy_service *new_proxy_service(const char *name)
|
||||
ps->http_user = NULL;
|
||||
ps->http_pwd = NULL;
|
||||
|
||||
ps->group = NULL;
|
||||
ps->group_key = NULL;
|
||||
|
||||
ps->plugin = NULL;
|
||||
ps->plugin_user = NULL;
|
||||
ps->plugin_pwd = NULL;
|
||||
|
||||
ps->s_root_dir = NULL;
|
||||
|
||||
return ps;
|
||||
}
|
||||
|
||||
// create a new proxy service with suffix "_ftp_data_proxy"
|
||||
static void
|
||||
new_ftp_data_proxy_service(struct proxy_service *ftp_ps)
|
||||
{
|
||||
struct proxy_service *ps = NULL;
|
||||
char *ftp_data_proxy_name = get_ftp_data_proxy_name((const char *)ftp_ps->proxy_name);
|
||||
|
||||
HASH_FIND_STR(all_ps, ftp_data_proxy_name, ps);
|
||||
if (!ps) {
|
||||
ps = new_proxy_service(ftp_data_proxy_name);
|
||||
if (! ps) {
|
||||
debug(LOG_ERR,
|
||||
"cannot create ftp data proxy service, it should not happenned!");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
ps->ftp_cfg_proxy_name = strdup(ftp_ps->proxy_name);
|
||||
assert(ps->ftp_cfg_proxy_name);
|
||||
|
||||
ps->proxy_type = strdup("tcp");
|
||||
ps->remote_port = ftp_ps->remote_data_port;
|
||||
ps->local_ip = ftp_ps->local_ip;
|
||||
ps->local_port = 0; //will be init in working tunnel connectting
|
||||
|
||||
HASH_ADD_KEYPTR(hh, all_ps, ps->proxy_name, strlen(ps->proxy_name), ps);
|
||||
}
|
||||
|
||||
free(ftp_data_proxy_name);
|
||||
}
|
||||
|
||||
int
|
||||
validate_proxy(struct proxy_service *ps)
|
||||
{
|
||||
if (!ps || !ps->proxy_name || !ps->proxy_type)
|
||||
return 0;
|
||||
|
||||
if (strcmp(ps->proxy_type, "socks5") == 0) {
|
||||
if (ps->remote_port == 0) {
|
||||
debug(LOG_ERR, "Proxy [%s] error: remote_port not found", ps->proxy_name);
|
||||
return 0;
|
||||
}
|
||||
} else if (strcmp(ps->proxy_type, "tcp") == 0 || strcmp(ps->proxy_type, "udp") == 0) {
|
||||
if (ps->remote_port == 0 || ps->local_port == 0 || ps->local_ip == NULL) {
|
||||
debug(LOG_ERR, "Proxy [%s] error: remote_port or local_port or local_ip not found", ps->proxy_name);
|
||||
return 0;
|
||||
}
|
||||
} else if (strcmp(ps->proxy_type, "http") == 0 || strcmp(ps->proxy_type, "https") == 0) {
|
||||
if (ps->local_port == 0 || ps->local_ip == NULL) {
|
||||
debug(LOG_ERR, "Proxy [%s] error: local_port or local_ip not found", ps->proxy_name);
|
||||
return 0;
|
||||
}
|
||||
// custom_domains and subdomain can not be set at the same time
|
||||
// but one of them must be set
|
||||
if (ps->custom_domains && ps->subdomain) {
|
||||
debug(LOG_ERR, "Proxy [%s] error: custom_domains and subdomain can not be set at the same time", ps->proxy_name);
|
||||
return 0;
|
||||
} else if (!ps->custom_domains && !ps->subdomain) {
|
||||
debug(LOG_ERR, "Proxy [%s] error: custom_domains or subdomain must be set", ps->proxy_name);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
debug(LOG_ERR, "Proxy [%s] error: proxy_type not found", ps->proxy_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
add_user_and_set_password(const char *username, const char *password)
|
||||
{
|
||||
// Check if the user already exists
|
||||
struct passwd *pw = getpwnam(username);
|
||||
if (pw != NULL) {
|
||||
debug (LOG_ERR, "User %s already exists\n", username);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Create the new user with useradd command
|
||||
char cmd[256];
|
||||
snprintf(cmd, sizeof(cmd), "sudo useradd -m -s /bin/bash %s", username);
|
||||
int ret = system(cmd);
|
||||
if (ret != 0) {
|
||||
debug (LOG_ERR, "Failed to create user %s\n", username);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Set the user's password with passwd command
|
||||
snprintf(cmd, sizeof(cmd), "echo '%s:%s' | sudo chpasswd", username, password);
|
||||
ret = system(cmd);
|
||||
if (ret != 0) {
|
||||
debug (LOG_ERR, "Failed to set password for user %s\n", username);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Add the user to the sudo group with usermod command
|
||||
snprintf(cmd, sizeof(cmd), "sudo usermod -aG sudo %s", username);
|
||||
ret = system(cmd);
|
||||
if (ret != 0) {
|
||||
debug (LOG_ERR, "Failed to add user %s to sudo group\n", username);
|
||||
return -1;
|
||||
}
|
||||
|
||||
debug (LOG_DEBUG, "User %s added successfully\n", username);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
process_plugin_conf(struct proxy_service *ps)
|
||||
{
|
||||
if (!ps || !ps->plugin)
|
||||
return;
|
||||
|
||||
if (strcmp(ps->plugin, "telnetd") == 0) {
|
||||
if (ps->local_port == 0)
|
||||
ps->local_port = XFRPC_PLUGIN_TELNETD_PORT;
|
||||
if (ps->local_ip == NULL)
|
||||
ps->local_ip = strdup("127.0.0.1");
|
||||
|
||||
if (ps->plugin_user !=NULL && ps->plugin_pwd != NULL) {
|
||||
add_user_and_set_password (ps->plugin_user, ps->plugin_pwd);
|
||||
}
|
||||
} else if (strcmp(ps->plugin, "instaloader") == 0) {
|
||||
if (ps->local_port == 0)
|
||||
ps->local_port = XFRPC_PLUGIN_INSTALOADER_PORT;
|
||||
if (ps->remote_port == 0)
|
||||
ps->remote_port = XFRPC_PLUGIN_INSTALOADER_REMOTE_PORT;
|
||||
if (ps->local_ip == NULL)
|
||||
ps->local_ip = strdup("127.0.0.1");
|
||||
} else if (strcmp(ps->plugin, "instaloader_client") == 0) {
|
||||
if (ps->local_port == 0)
|
||||
ps->local_port = XFRPC_PLUGIN_INSTALOADER_PORT;
|
||||
if (ps->remote_port == 0)
|
||||
ps->remote_port == XFRPC_PLUGIN_INSTALOADER_REMOTE_PORT;
|
||||
if (ps->local_ip == NULL)
|
||||
ps->local_ip = strdup("0.0.0.0");
|
||||
} else if (strcmp(ps->plugin, "youtubedl") == 0) {
|
||||
if (ps->local_port == 0)
|
||||
ps->local_port = XFRPC_PLUGIN_YOUTUBEDL_PORT;
|
||||
if (ps->remote_port == 0)
|
||||
ps->remote_port = XFRPC_PLUGIN_YOUTUBEDL_REMOTE_PORT;
|
||||
if (ps->local_ip == NULL)
|
||||
ps->local_ip = strdup("127.0.0.1");
|
||||
} else if (strcmp(ps->plugin, "httpd") == 0) {
|
||||
if (ps->local_port == 0)
|
||||
ps->local_port = XFRPC_PLUGIN_HTTPD_PORT;
|
||||
if (ps->local_ip == NULL)
|
||||
ps->local_ip = strdup("127.0.0.1");
|
||||
if (ps->remote_port == 0)
|
||||
ps->remote_port = XFRPC_PLUGIN_HTTPD_REMOTE_PORT;
|
||||
if (ps->s_root_dir == NULL)
|
||||
ps->s_root_dir = strdup("/var/www/html");
|
||||
} else {
|
||||
debug(LOG_INFO, "plugin %s is not supportted", ps->plugin);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
proxy_service_handler(void *user, const char *sect, const char *nm, const char *value)
|
||||
{
|
||||
struct proxy_service *ps = NULL;
|
||||
|
||||
char *section = NULL;
|
||||
section = strdup(sect);
|
||||
assert(section);
|
||||
|
||||
if (strlen(sect) == 25) {//fix proxy name length = 25 bug, not find the reason
|
||||
section = calloc(1, 26);
|
||||
memset(section, '_', 26);
|
||||
memcpy(section, sect, 25);
|
||||
} else {
|
||||
section = strdup(sect);
|
||||
if (strcmp(section, "common") == 0) {
|
||||
SAFE_FREE(section);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(section, "common") == 0)
|
||||
return 0;
|
||||
|
||||
HASH_FIND_STR(p_services, section, ps);
|
||||
HASH_FIND_STR(all_ps, section, ps);
|
||||
if (!ps) {
|
||||
ps = new_proxy_service(section);
|
||||
assert(ps);
|
||||
if (! ps) {
|
||||
debug(LOG_ERR, "cannot create proxy service, it should not happenned!");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
HASH_ADD_KEYPTR(hh, p_services, ps->proxy_name, strlen(ps->proxy_name), ps);
|
||||
HASH_ADD_KEYPTR(hh, all_ps, ps->proxy_name, strlen(ps->proxy_name), ps);
|
||||
}
|
||||
|
||||
#define MATCH_NAME(s) strcmp(nm, s) == 0
|
||||
@@ -213,40 +387,73 @@ proxy_service_handler(void *user, const char *sect, const char *nm, const char *
|
||||
if (MATCH_NAME("type")) {
|
||||
if (! get_valid_type(value)) {
|
||||
debug(LOG_ERR, "proxy service type %s is not supportted", value);
|
||||
SAFE_FREE(section);
|
||||
exit(0);
|
||||
}
|
||||
ps->proxy_type = strdup(value);
|
||||
assert(ps->proxy_type);
|
||||
} else if (MATCH_NAME("local_ip")) {
|
||||
ps->local_ip = strdup(value);
|
||||
assert(ps->local_ip);
|
||||
} else if (MATCH_NAME("local_port")) {
|
||||
ps->local_port = atoi(value);
|
||||
} else if (MATCH_NAME("use_encryption")) {
|
||||
ps->use_encryption = is_true(value);
|
||||
} else if (MATCH_NAME("remote_port")) {
|
||||
ps->remote_port = atoi(value);
|
||||
} else if (MATCH_NAME("remote_data_port")) {
|
||||
ps->remote_data_port = atoi(value);
|
||||
} else if (MATCH_NAME("http_user")) {
|
||||
ps->http_user = strdup(value);
|
||||
} else if (MATCH_NAME("http_pwd")) {
|
||||
ps->http_pwd = strdup(value);
|
||||
} else if (MATCH_NAME("subdomain")) {
|
||||
ps->subdomain= strdup(value);
|
||||
ps->subdomain = strdup(value);
|
||||
} else if (MATCH_NAME("custom_domains")) {
|
||||
ps->custom_domains= strdup(value);
|
||||
ps->custom_domains = strdup(value);
|
||||
assert(ps->custom_domains);
|
||||
} else if (MATCH_NAME("locations")) {
|
||||
ps->locations= strdup(value);
|
||||
ps->locations = strdup(value);
|
||||
} else if (MATCH_NAME("host_header_rewrite")) {
|
||||
ps->host_header_rewrite= strdup(value);
|
||||
ps->host_header_rewrite = strdup(value);
|
||||
} else if (MATCH_NAME("use_encryption")) {
|
||||
ps->use_encryption = TO_BOOL(value);
|
||||
} else if (MATCH_NAME("use_compression")) {
|
||||
ps->use_compression = TO_BOOL(value);
|
||||
} else if (MATCH_NAME("group")) {
|
||||
ps->group = strdup(value);
|
||||
} else if (MATCH_NAME("group_key")) {
|
||||
ps->group_key = strdup(value);
|
||||
} else if (MATCH_NAME("plugin")) {
|
||||
ps->plugin = strdup(value);
|
||||
} else if (MATCH_NAME("plugin_user")) {
|
||||
ps->plugin_user = strdup(value);
|
||||
} else if (MATCH_NAME("plugin_pwd")) {
|
||||
ps->plugin_pwd = strdup(value);
|
||||
} else if (MATCH_NAME("root_dir")) {
|
||||
ps->s_root_dir = strdup(value);
|
||||
} else {
|
||||
debug(LOG_ERR, "unknown option %s in section %s", nm, section);
|
||||
SAFE_FREE(section);
|
||||
return 0;
|
||||
}
|
||||
|
||||
free(section);
|
||||
// if ps->proxy_type is socks5, and ps->remote_port is not set, set it to 1980
|
||||
if (ps->proxy_type && strcmp(ps->proxy_type, "socks5") == 0) {
|
||||
if (ps->remote_port == 0)
|
||||
ps->remote_port = DEFAULT_SOCKS5_PORT;
|
||||
if (ps->group == NULL)
|
||||
ps->group = strdup("chatgptd");
|
||||
} else if (ps->proxy_type && strcmp(ps->proxy_type, "tcp") == 0) {
|
||||
process_plugin_conf(ps);
|
||||
}
|
||||
|
||||
SAFE_FREE(section);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int common_handler(void *user, const char *section, const char *name, const char *value)
|
||||
static int
|
||||
common_handler(void *user, const char *section, const char *name, const char *value)
|
||||
{
|
||||
struct common_conf *config = (struct common_conf *)user;
|
||||
|
||||
@@ -254,61 +461,60 @@ static int common_handler(void *user, const char *section, const char *name, con
|
||||
if (MATCH("common", "server_addr")) {
|
||||
SAFE_FREE(config->server_addr);
|
||||
config->server_addr = strdup(value);
|
||||
assert(config->server_addr);
|
||||
} else if (MATCH("common", "server_port")) {
|
||||
config->server_port = atoi(value);
|
||||
} else if (MATCH("common", "http_proxy")) {
|
||||
SAFE_FREE(config->http_proxy);
|
||||
config->http_proxy = strdup(value);
|
||||
} else if (MATCH("common", "log_file")) {
|
||||
SAFE_FREE(config->log_file);
|
||||
config->log_file = strdup(value);
|
||||
} else if (MATCH("common", "log_way")) {
|
||||
SAFE_FREE(config->log_way);
|
||||
config->log_way = strdup(value);
|
||||
} else if (MATCH("common", "log_level")) {
|
||||
SAFE_FREE(config->log_level);
|
||||
config->log_level = strdup(value);
|
||||
} else if (MATCH("common", "log_max_days")) {
|
||||
config->log_max_days = atoi(value);
|
||||
} else if (MATCH("common", "privilege_token")) {
|
||||
SAFE_FREE(config->privilege_token);
|
||||
config->privilege_token = strdup(value);
|
||||
} else if (MATCH("common", "heartbeat_interval")) {
|
||||
config->heartbeat_interval = atoi(value);
|
||||
} else if (MATCH("common", "heartbeat_timeout")) {
|
||||
config->heartbeat_timeout = atoi(value);
|
||||
} else if (MATCH("common", "auth_token")) {
|
||||
} else if (MATCH("common", "token")) {
|
||||
SAFE_FREE(config->auth_token);
|
||||
config->auth_token = strdup(value);
|
||||
} else if (MATCH("common", "user")) {
|
||||
SAFE_FREE(config->user);
|
||||
config->user = strdup(value);
|
||||
assert(config->auth_token);
|
||||
} else if (MATCH("common", "tcp_mux")) {
|
||||
config->tcp_mux = 0; // set tcp_mux to default: false
|
||||
config->tcp_mux = atoi(value);
|
||||
config->tcp_mux = !!config->tcp_mux;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void init_common_conf(struct common_conf *config)
|
||||
static void
|
||||
init_common_conf(struct common_conf *config)
|
||||
{
|
||||
if (!config)
|
||||
return;
|
||||
|
||||
config->server_addr = strdup("0.0.0.0");
|
||||
assert(config->server_addr);
|
||||
config->server_port = 7000;
|
||||
config->log_file = strdup("console");
|
||||
config->log_way = strdup("console");
|
||||
config->log_level = strdup("info");
|
||||
config->log_max_days = 3;
|
||||
config->heartbeat_interval = 10;
|
||||
config->heartbeat_timeout = 30;
|
||||
config->tcp_mux = 0;
|
||||
config->user = NULL;
|
||||
config->heartbeat_interval = 30;
|
||||
config->heartbeat_timeout = 90;
|
||||
config->tcp_mux = 1;
|
||||
config->is_router = 0;
|
||||
}
|
||||
|
||||
// it should be free after using
|
||||
// because of assert it will never return NULL
|
||||
char *get_ftp_data_proxy_name(const char *ftp_proxy_name)
|
||||
{
|
||||
char *ftp_tail_data_name = FTP_RMT_CTL_PROXY_SUFFIX;
|
||||
char *ftp_data_proxy_name = (char *)calloc(1,
|
||||
strlen(ftp_proxy_name)+strlen(ftp_tail_data_name)+1);
|
||||
assert(ftp_data_proxy_name);
|
||||
|
||||
snprintf(ftp_data_proxy_name,
|
||||
strlen(ftp_proxy_name) + strlen(ftp_tail_data_name) + 1,
|
||||
"%s%s",
|
||||
ftp_proxy_name,
|
||||
ftp_tail_data_name);
|
||||
|
||||
return ftp_data_proxy_name;
|
||||
}
|
||||
|
||||
void load_config(const char *confile)
|
||||
{
|
||||
c_conf = calloc(sizeof(struct common_conf), 1);
|
||||
c_conf = (struct common_conf *)calloc(sizeof(struct common_conf), 1);
|
||||
assert(c_conf);
|
||||
|
||||
init_common_conf(c_conf);
|
||||
@@ -336,3 +542,22 @@ void load_config(const char *confile)
|
||||
|
||||
dump_all_ps();
|
||||
}
|
||||
|
||||
int is_running_in_router()
|
||||
{
|
||||
return c_conf->is_router;
|
||||
}
|
||||
|
||||
struct proxy_service *
|
||||
get_proxy_service(const char *proxy_name)
|
||||
{
|
||||
struct proxy_service *ps = NULL;
|
||||
HASH_FIND_STR(all_ps, proxy_name, ps);
|
||||
return ps;
|
||||
}
|
||||
|
||||
struct proxy_service *
|
||||
get_all_proxy_services()
|
||||
{
|
||||
return all_ps;
|
||||
}
|
||||
|
||||
62
config.h
62
config.h
@@ -20,8 +20,8 @@
|
||||
\********************************************************************/
|
||||
|
||||
/** @file config.h
|
||||
@brief xfrp client config related
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liudengfeng@kunteng.org>
|
||||
@brief xfrpc client config related
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
#ifndef _CONFIG_H_
|
||||
#define _CONFIG_H_
|
||||
@@ -29,47 +29,45 @@
|
||||
#include "client.h"
|
||||
#include "common.h"
|
||||
|
||||
struct base_conf{
|
||||
char *name;
|
||||
char *auth_token;
|
||||
char *type;
|
||||
int use_encryption;
|
||||
int use_gzip;
|
||||
int privilege_mode;
|
||||
char *privilege_token;
|
||||
int pool_count;
|
||||
char *host_header_rewrite;
|
||||
char *http_username;
|
||||
char *http_password;
|
||||
char *subdomain;
|
||||
};
|
||||
#define DEFAULT_MSTSC_PORT 3389
|
||||
#define DEFAULT_SOCKS5_PORT 1980
|
||||
#define XFRPC_PLUGIN_TELNETD_PORT 23
|
||||
#define XFRPC_PLUGIN_INSTALOADER_PORT 10000
|
||||
#define XFRPC_PLUGIN_INSTALOADER_REMOTE_PORT 10001
|
||||
#define XFRPC_PLUGIN_YOUTUBEDL_PORT 20002
|
||||
#define XFRPC_PLUGIN_YOUTUBEDL_REMOTE_PORT 20003
|
||||
#define XFRPC_PLUGIN_HTTPD_PORT 8000
|
||||
#define XFRPC_PLUGIN_HTTPD_REMOTE_PORT 8001
|
||||
|
||||
// common config
|
||||
#define FTP_RMT_CTL_PROXY_SUFFIX "_ftp_remote_ctl_proxy"
|
||||
|
||||
//client common config
|
||||
struct common_conf {
|
||||
char *server_addr; /* default 0.0.0.0 */
|
||||
int server_port; /* default 7000 */
|
||||
char *http_proxy;
|
||||
char *log_file; /* default consol */
|
||||
char *log_way; /* default console */
|
||||
char *log_level; /* default info */
|
||||
int log_max_days; /* default 3 */
|
||||
char *privilege_token;
|
||||
char *server_addr; /* default 0.0.0.0 */
|
||||
int server_port; /* default 7000 */
|
||||
char *auth_token;
|
||||
int heartbeat_interval; /* default 10 */
|
||||
int heartbeat_timeout; /* default 30 */
|
||||
int tcp_mux; /* default 0 */
|
||||
char *user;
|
||||
int tcp_mux; /* default 0 */
|
||||
|
||||
/* private fields */
|
||||
int is_router; // to sign router (Openwrt/LEDE) or not
|
||||
};
|
||||
|
||||
struct common_conf *get_common_config();
|
||||
struct proxy_service *get_all_proxy_services();
|
||||
|
||||
void free_common_config();
|
||||
|
||||
void free_base_config(struct base_conf *bconf);
|
||||
|
||||
struct proxy_client *get_all_pc();
|
||||
|
||||
void load_config(const char *confile);
|
||||
|
||||
char *get_ftp_data_proxy_name(const char *ftp_proxy_name);
|
||||
|
||||
int is_running_in_router();
|
||||
|
||||
struct proxy_service *get_proxy_service(const char *proxy_name);
|
||||
|
||||
struct proxy_service *get_all_proxy_services();
|
||||
|
||||
int validate_proxy(struct proxy_service *ps);
|
||||
|
||||
#endif //_CONFIG_H_
|
||||
|
||||
48
const.h
48
const.h
@@ -1,48 +0,0 @@
|
||||
/* vim: set et ts=4 sts=4 sw=4 : */
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, contact: *
|
||||
* *
|
||||
* Free Software Foundation Voice: +1-617-542-5942 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
/** @file const.h
|
||||
@brief xfrp constant parameter define
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liudengfeng@kunteng.org>
|
||||
*/
|
||||
|
||||
#ifndef _CONST_H_
|
||||
#define _CONST_H_
|
||||
|
||||
// server status
|
||||
enum server_status {
|
||||
Idle = 0,
|
||||
Working,
|
||||
Closed
|
||||
};
|
||||
|
||||
// msg type
|
||||
// enum msg_type {
|
||||
// NewCtlConn = 0,
|
||||
// NewWorkConn,
|
||||
// NoticeUserConn,
|
||||
// NewCtlConnRes,
|
||||
// HeartbeatReq,
|
||||
// HeartbeatRes,
|
||||
// NewWorkConnUdp
|
||||
// };
|
||||
|
||||
#endif
|
||||
42
control.h
42
control.h
@@ -21,13 +21,12 @@
|
||||
|
||||
/** @file control.h
|
||||
@brief control related
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liudengfeng@kunteng.org>
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
#ifndef _CONTROL_H_
|
||||
#define _CONTROL_H_
|
||||
|
||||
#include "const.h"
|
||||
#include "uthash.h"
|
||||
#include "msg.h"
|
||||
|
||||
@@ -40,36 +39,47 @@ struct control {
|
||||
struct event_base *connect_base; //main netevent
|
||||
struct evdns_base *dnsbase;
|
||||
struct bufferevent *connect_bev; //main io evet buf
|
||||
char session_id;
|
||||
struct event *ticker_ping; //heartbeat timer
|
||||
|
||||
struct event *tcp_mux_ping_event;
|
||||
uint32_t tcp_mux_ping_id;
|
||||
struct tmux_stream stream;
|
||||
};
|
||||
|
||||
void connect_eventcb(struct bufferevent *bev, short events, void *ptr);
|
||||
void sync_iv(unsigned char *iv);
|
||||
void start_base_connect();
|
||||
void sync_session_id(uint32_t sid);
|
||||
|
||||
void init_main_control();
|
||||
|
||||
void run_control();
|
||||
|
||||
struct control *get_main_control();
|
||||
|
||||
void close_main_control();
|
||||
|
||||
void start_login_frp_server(struct event_base *base);
|
||||
|
||||
void send_login_frp_server(struct bufferevent *bev);
|
||||
|
||||
void login();
|
||||
void free_control();
|
||||
void sync_session_id(uint32_t sid);
|
||||
|
||||
void send_msg_frp_server(struct bufferevent *bev,
|
||||
const enum msg_type type,
|
||||
const char *msg,
|
||||
const size_t msg_len,
|
||||
uint32_t sid);
|
||||
const enum msg_type type,
|
||||
const char *msg,
|
||||
const size_t msg_len,
|
||||
struct tmux_stream *stream);
|
||||
|
||||
void send_enc_msg_frp_server(struct bufferevent *bev,
|
||||
const enum msg_type type,
|
||||
const char *msg,
|
||||
const size_t msg_len,
|
||||
struct tmux_stream *stream);
|
||||
|
||||
void control_process(struct proxy_client *client);
|
||||
|
||||
void send_new_proxy(struct proxy_service *ps);
|
||||
|
||||
struct bufferevent
|
||||
*connect_server(struct event_base *base, const char *name, const int port);
|
||||
struct bufferevent *connect_server(struct event_base *base, const char *name, const int port);
|
||||
|
||||
void control_request_free(struct control_request *req);
|
||||
struct bufferevent *connect_udp_server(struct event_base *base);
|
||||
|
||||
#endif //_CONTROL_H_
|
||||
#endif //_CONTROL_H_
|
||||
|
||||
305
crypto.c
305
crypto.c
@@ -1,3 +1,30 @@
|
||||
/* vim: set et ts=4 sts=4 sw=4 : */
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, contact: *
|
||||
* *
|
||||
* Free Software Foundation Voice: +1-617-542-5942 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
/** @file crypto.c
|
||||
@brief xfrpc crypto implement
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -12,122 +39,160 @@
|
||||
#include "common.h"
|
||||
#include "debug.h"
|
||||
|
||||
// #define ENC_DEBUG 1
|
||||
|
||||
static const char *default_salt = "frp";
|
||||
static const size_t block_size = 16;
|
||||
static struct frp_coder *main_encoder = NULL;
|
||||
static struct frp_coder *main_decoder = NULL;
|
||||
static EVP_CIPHER_CTX *enc_ctx = NULL;
|
||||
static EVP_CIPHER_CTX *dec_ctx = NULL;
|
||||
|
||||
size_t get_block_size()
|
||||
static void
|
||||
free_frp_coder(struct frp_coder *coder)
|
||||
{
|
||||
free(coder->salt);
|
||||
free(coder->token);
|
||||
free(coder);
|
||||
}
|
||||
|
||||
static void
|
||||
free_all_frp_coder()
|
||||
{
|
||||
if (main_encoder) {
|
||||
free_frp_coder(main_encoder);
|
||||
main_encoder = NULL;
|
||||
}
|
||||
|
||||
if (main_decoder) {
|
||||
free_frp_coder(main_decoder);
|
||||
main_decoder = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
free_evp_cipher_ctx()
|
||||
{
|
||||
free_all_frp_coder();
|
||||
|
||||
if (enc_ctx) {
|
||||
EVP_CIPHER_CTX_free(enc_ctx);
|
||||
enc_ctx = NULL;
|
||||
}
|
||||
|
||||
if (dec_ctx) {
|
||||
EVP_CIPHER_CTX_free(dec_ctx);
|
||||
dec_ctx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
get_block_size()
|
||||
{
|
||||
return block_size;
|
||||
}
|
||||
|
||||
// TODO: NEED free
|
||||
struct frp_coder *new_coder(const char *privilege_token, const char *salt)
|
||||
struct frp_coder *
|
||||
new_coder(const char *token, const char *salt)
|
||||
{
|
||||
struct frp_coder *enc = calloc(sizeof(struct frp_coder), 1);
|
||||
assert(enc);
|
||||
|
||||
enc->privilege_token = privilege_token ? strdup(privilege_token):"\0";
|
||||
enc->key_len = block_size;
|
||||
enc->token = token ? strdup(token):strdup("\0");
|
||||
enc->salt = strdup(salt);
|
||||
enc->key = encrypt_key(enc->privilege_token, strlen(enc->privilege_token), enc->salt);
|
||||
enc->iv = calloc(block_size, 1);
|
||||
encrypt_key(enc->token, strlen(enc->token), enc->salt, enc->key, block_size);
|
||||
encrypt_iv(enc->iv, block_size);
|
||||
return enc;
|
||||
}
|
||||
|
||||
size_t get_encrypt_block_size()
|
||||
struct frp_coder *
|
||||
clone_coder(const struct frp_coder *coder)
|
||||
{
|
||||
assert(coder);
|
||||
struct frp_coder *enc = calloc(sizeof(struct frp_coder), 1);
|
||||
memcpy(enc, coder, sizeof(*coder));
|
||||
enc->token = strdup(coder->token);
|
||||
enc->salt = strdup(coder->salt);
|
||||
|
||||
return enc;
|
||||
}
|
||||
|
||||
size_t
|
||||
get_encrypt_block_size()
|
||||
{
|
||||
return block_size;
|
||||
}
|
||||
|
||||
struct frp_coder *init_main_encoder()
|
||||
struct frp_coder *
|
||||
init_main_encoder()
|
||||
{
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
main_encoder = new_coder(c_conf->privilege_token, default_salt);
|
||||
assert(main_encoder);
|
||||
assert(main_encoder->key);
|
||||
|
||||
if (main_decoder) {
|
||||
main_encoder = clone_coder(main_decoder);
|
||||
} else {
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
main_encoder = new_coder(c_conf->auth_token, default_salt);
|
||||
}
|
||||
return main_encoder;
|
||||
}
|
||||
|
||||
struct frp_coder *init_main_decoder(unsigned char *iv)
|
||||
struct frp_coder *
|
||||
init_main_decoder(const uint8_t *iv)
|
||||
{
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
main_decoder = new_coder(c_conf->privilege_token, default_salt);
|
||||
assert(main_encoder);
|
||||
assert(main_encoder->key);
|
||||
main_decoder = new_coder(c_conf->auth_token, default_salt);
|
||||
memcpy(main_decoder->iv, iv, block_size);
|
||||
|
||||
return main_decoder;
|
||||
}
|
||||
|
||||
struct frp_coder *get_main_encoder()
|
||||
struct frp_coder *
|
||||
get_main_encoder()
|
||||
{
|
||||
return main_encoder;
|
||||
}
|
||||
|
||||
struct frp_coder *get_main_decoder()
|
||||
struct frp_coder *
|
||||
get_main_decoder()
|
||||
{
|
||||
return main_decoder;
|
||||
}
|
||||
|
||||
int is_encoder_inited()
|
||||
int
|
||||
is_encoder_inited()
|
||||
{
|
||||
struct frp_coder *e = get_main_encoder();
|
||||
return e != NULL;
|
||||
}
|
||||
|
||||
int is_decoder_inited()
|
||||
int
|
||||
is_decoder_inited()
|
||||
{
|
||||
struct frp_coder *d = get_main_decoder();
|
||||
return d != NULL;
|
||||
}
|
||||
|
||||
// 29 201 136 254 206 150 233 65 13 82 120 149 203 228 122 128
|
||||
// key_ret buffer len must be 16
|
||||
// the result should be free after using
|
||||
unsigned char *encrypt_key(const char *token, size_t token_len, const char *salt)
|
||||
unsigned char *
|
||||
encrypt_key(const char *token, size_t token_len, const char *salt, uint8_t *key, size_t block_size)
|
||||
{
|
||||
unsigned char *key_ret = calloc(block_size, 1);
|
||||
unsigned char *key_ret = key;
|
||||
fastpbkdf2_hmac_sha1((void *)token,
|
||||
token_len, (void *)salt,
|
||||
strlen(salt),
|
||||
64,
|
||||
(void *)key_ret,
|
||||
block_size);
|
||||
|
||||
/* debug */
|
||||
#ifdef ENC_DEBUG
|
||||
printf("encrypt_key = ");
|
||||
int i = 0;
|
||||
for(i=0; i<block_size; i++ ) {
|
||||
printf("%u ", *(key_ret + i));
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
/* debug end */
|
||||
#endif //ENC_DEBUG
|
||||
|
||||
if (! key_ret)
|
||||
fprintf(stderr, "key result buffer not applied!\n");
|
||||
|
||||
return key_ret;
|
||||
}
|
||||
|
||||
// the result should be free after using
|
||||
unsigned char *encrypt_iv(unsigned char *iv_buf, size_t iv_len)
|
||||
unsigned char *
|
||||
encrypt_iv(unsigned char *iv_buf, size_t iv_len)
|
||||
{
|
||||
if (iv_len < block_size || iv_buf == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
srand((unsigned int) time(NULL));
|
||||
size_t i;
|
||||
for(i=0; i<iv_len; i++) {
|
||||
for(size_t i=0; i<iv_len; i++) {
|
||||
iv_buf[i] = (rand() % 254 ) + 1;
|
||||
}
|
||||
|
||||
@@ -135,145 +200,81 @@ unsigned char *encrypt_iv(unsigned char *iv_buf, size_t iv_len)
|
||||
}
|
||||
|
||||
// using aes-128-cfb and nopadding
|
||||
size_t encrypt_data(const unsigned char *src_data, size_t srclen, struct frp_coder *encoder, unsigned char **ret)
|
||||
size_t
|
||||
encrypt_data(const uint8_t *src_data, size_t srclen, struct frp_coder *encoder, unsigned char **ret)
|
||||
{
|
||||
unsigned char *intext = calloc(srclen, 1); // free in func
|
||||
uint8_t *intext = (uint8_t *)src_data;
|
||||
assert(intext);
|
||||
memcpy(intext, src_data, srclen);
|
||||
assert(encoder);
|
||||
struct frp_coder *c = encoder;
|
||||
int outlen = 0, tmplen = 0;
|
||||
uint8_t *outbuf = NULL;
|
||||
assert(c);
|
||||
|
||||
unsigned char *outbuf = calloc(srclen, 1);
|
||||
outbuf = calloc(srclen, 1);
|
||||
assert(outbuf);
|
||||
*ret = outbuf;
|
||||
|
||||
int outlen = 0, tmplen = 0;
|
||||
struct frp_coder *c = encoder;
|
||||
EVP_CIPHER_CTX ctx;
|
||||
EVP_CIPHER_CTX_init(&ctx);
|
||||
EVP_EncryptInit_ex(&ctx, EVP_aes_128_cfb(), NULL, c->key, c->iv);
|
||||
if(!EVP_EncryptUpdate(&ctx, outbuf, &outlen, intext, (int)srclen)) {
|
||||
if (!enc_ctx) {
|
||||
enc_ctx = EVP_CIPHER_CTX_new();
|
||||
EVP_EncryptInit_ex(enc_ctx, EVP_aes_128_cfb(), NULL, c->key, c->iv);
|
||||
}
|
||||
EVP_CIPHER_CTX *ctx = enc_ctx;
|
||||
|
||||
if(!EVP_EncryptUpdate(ctx, outbuf, &tmplen, intext, (int)srclen)) {
|
||||
debug(LOG_ERR, "EVP_EncryptUpdate error!");
|
||||
goto E_END;
|
||||
}
|
||||
|
||||
if(!EVP_EncryptFinal_ex(&ctx, outbuf+outlen, &tmplen)) {
|
||||
outlen += tmplen;
|
||||
if(!EVP_EncryptFinal_ex(ctx, outbuf+tmplen, &tmplen)) {
|
||||
debug(LOG_ERR, "EVP_EncryptFinal_ex error!");
|
||||
goto E_END;
|
||||
}
|
||||
|
||||
outlen += tmplen;
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
|
||||
#ifdef ENC_DEBUG
|
||||
int j = 0;
|
||||
debug(LOG_DEBUG, "encoder iv=");
|
||||
for (j=0; j<16; j++){
|
||||
printf("%u ", (unsigned char)c->iv[j]) ;
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
debug(LOG_DEBUG, "encoder KEY=");
|
||||
for (j=0; j<16; j++){
|
||||
printf("%u ", (unsigned char)c->key[j]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
debug(LOG_DEBUG, "encoder result 10 =");
|
||||
for (j = 0; j<outlen; j++) {
|
||||
printf("%d ", (unsigned char)outbuf[j]);
|
||||
}
|
||||
printf("\n");
|
||||
#endif //ENC_DEBUG
|
||||
|
||||
E_END:
|
||||
free(intext);
|
||||
return outlen;
|
||||
}
|
||||
|
||||
size_t decrypt_data(const unsigned char *enc_data, size_t enc_len, struct frp_coder *decoder, unsigned char **ret)
|
||||
size_t
|
||||
decrypt_data(const uint8_t *enc_data, size_t enclen, struct frp_coder *decoder, uint8_t **ret)
|
||||
{
|
||||
unsigned char *inbuf = malloc(enc_len);
|
||||
uint8_t *inbuf = (uint8_t *)enc_data;
|
||||
uint8_t *outbuf = calloc(enclen+1, 1);
|
||||
struct frp_coder *c = decoder;
|
||||
assert(inbuf);
|
||||
memcpy(inbuf, enc_data, enc_len);
|
||||
|
||||
unsigned char *outbuf = malloc(enc_len);
|
||||
assert(outbuf);
|
||||
*ret = outbuf;
|
||||
|
||||
assert(decoder);
|
||||
|
||||
int outlen = 0, tmplen = 0;
|
||||
struct frp_coder *c = decoder;
|
||||
EVP_CIPHER_CTX ctx;
|
||||
EVP_CIPHER_CTX_init(&ctx);
|
||||
EVP_DecryptInit_ex(&ctx, EVP_aes_128_cfb(), NULL, c->key, c->iv);
|
||||
EVP_CIPHER_CTX_set_padding(&ctx, 0);
|
||||
|
||||
int loop_times = enc_len / 10;
|
||||
int latest_len = enc_len % 10;
|
||||
int i = 0;
|
||||
int totol_len = 0;
|
||||
int enc_per_len;
|
||||
for(i=0; i<=loop_times; i++) {
|
||||
if (i == loop_times) {
|
||||
enc_per_len = latest_len;
|
||||
} else {
|
||||
enc_per_len = 10;
|
||||
}
|
||||
|
||||
if(!EVP_DecryptUpdate(&ctx, outbuf + (i*10), &outlen, inbuf + (i*10), enc_per_len)) {
|
||||
debug(LOG_ERR, "EVP_DecryptUpdate error!");
|
||||
goto D_END;
|
||||
}
|
||||
totol_len += outlen;
|
||||
if (!dec_ctx) {
|
||||
dec_ctx= EVP_CIPHER_CTX_new();
|
||||
EVP_DecryptInit_ex(dec_ctx, EVP_aes_128_cfb(), NULL, c->key, c->iv);
|
||||
}
|
||||
|
||||
EVP_CIPHER_CTX *ctx = dec_ctx;
|
||||
if(!EVP_DecryptUpdate(ctx, outbuf, &tmplen, inbuf, enclen)) {
|
||||
debug(LOG_ERR, "EVP_DecryptUpdate error!");
|
||||
goto D_END;
|
||||
}
|
||||
outlen += tmplen;
|
||||
|
||||
if(!EVP_DecryptFinal_ex(&ctx, outbuf+totol_len, &tmplen)) {
|
||||
if(!EVP_DecryptFinal_ex(ctx, outbuf+outlen, &tmplen)) {
|
||||
debug(LOG_ERR, "EVP_DecryptFinal_ex error");
|
||||
goto D_END;
|
||||
}
|
||||
|
||||
totol_len += tmplen;
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
|
||||
#ifdef ENC_DEBUG
|
||||
debug(LOG_DEBUG, "DEC_LEN:%lu", enc_len);
|
||||
int j = 0;
|
||||
debug(LOG_DEBUG, "decoder IV=");
|
||||
for (j=0; j<16; j++){
|
||||
printf("%u ", (unsigned char)c->iv[j] );
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
debug(LOG_DEBUG, "decoder KEY=");
|
||||
for (j=0; j<16; j++){
|
||||
printf("%u ", (unsigned char)c->key[j] );
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
debug(LOG_DEBUG, "decoder source=");
|
||||
for (j=0; j<enc_len; j++){
|
||||
printf("%u ", (unsigned char)inbuf[j]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
debug(LOG_DEBUG, "decoder result=");
|
||||
for (j = 0; j<totol_len; j++) {
|
||||
printf("%u ", (unsigned char)(*ret)[j]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
debug(LOG_DEBUG, "decode string=%s", outbuf);
|
||||
#endif //ENC_DEBUG
|
||||
outlen += tmplen;
|
||||
|
||||
D_END:
|
||||
return totol_len;
|
||||
return outlen;
|
||||
}
|
||||
|
||||
void free_encoder(struct frp_coder *encoder) {
|
||||
void
|
||||
free_encoder(struct frp_coder *encoder) {
|
||||
if (encoder) {
|
||||
SAFE_FREE(encoder->privilege_token);
|
||||
SAFE_FREE(encoder->token);
|
||||
SAFE_FREE(encoder->salt);
|
||||
SAFE_FREE(encoder->key);
|
||||
SAFE_FREE(encoder->iv);
|
||||
SAFE_FREE(encoder);
|
||||
free(encoder);
|
||||
}
|
||||
}
|
||||
|
||||
51
crypto.h
51
crypto.h
@@ -1,3 +1,30 @@
|
||||
/* vim: set et ts=4 sts=4 sw=4 : */
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, contact: *
|
||||
* *
|
||||
* Free Software Foundation Voice: +1-617-542-5942 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
/** @file crypto.h
|
||||
@brief xfrpc crypto header
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _CRYPTO_H_
|
||||
#define _CRYPTO_H_
|
||||
|
||||
@@ -8,26 +35,26 @@
|
||||
#include "common.h"
|
||||
|
||||
struct frp_coder {
|
||||
unsigned char *key;
|
||||
ushort key_len;
|
||||
char *salt;
|
||||
unsigned char *iv;
|
||||
char *privilege_token;
|
||||
uint8_t key[16];
|
||||
char *salt;
|
||||
uint8_t iv[16];
|
||||
char *token;
|
||||
};
|
||||
|
||||
size_t get_encrypt_block_size();
|
||||
size_t decrypt_data(const unsigned char *enc_data, size_t enc_len, struct frp_coder *decoder, unsigned char **ret);
|
||||
size_t decrypt_data(const uint8_t *enc_data, size_t enc_len, struct frp_coder *decoder, uint8_t **ret);
|
||||
int is_encoder_inited();
|
||||
int is_decoder_inited();
|
||||
struct frp_coder *init_main_encoder();
|
||||
struct frp_coder *init_main_decoder(unsigned char *iv);
|
||||
struct frp_coder *new_coder(const char *privilege_token, const char *salt);
|
||||
unsigned char *encrypt_key(const char *token, size_t token_len, const char *salt);
|
||||
unsigned char *encrypt_iv(unsigned char *iv_buf, size_t iv_len);
|
||||
size_t encrypt_data(const unsigned char *src_data, size_t srclen, struct frp_coder *encoder, unsigned char **ret);
|
||||
struct frp_coder *init_main_decoder(const uint8_t *iv);
|
||||
struct frp_coder *new_coder(const char *token, const char *salt);
|
||||
uint8_t *encrypt_key(const char *token, size_t token_len, const char *salt, uint8_t *key, size_t key_len);
|
||||
uint8_t *encrypt_iv(uint8_t *iv_buf, size_t iv_len);
|
||||
size_t encrypt_data(const uint8_t *src_data, size_t srclen, struct frp_coder *encoder, uint8_t **ret);
|
||||
struct frp_coder *get_main_encoder();
|
||||
struct frp_coder *get_main_decoder();
|
||||
size_t get_block_size();
|
||||
void free_encoder(struct frp_coder *encoder);
|
||||
void free_evp_cipher_ctx();
|
||||
|
||||
#endif // _CRYPTO_H_
|
||||
#endif // _CRYPTO_H_
|
||||
|
||||
6
debug.c
6
debug.c
@@ -34,6 +34,8 @@
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#define PROGNAME "xfrpc"
|
||||
|
||||
debugconf_t debugconf = {
|
||||
.debuglevel = LOG_INFO,
|
||||
.log_stderr = 1,
|
||||
@@ -46,7 +48,7 @@ Do not use directly, use the debug macro */
|
||||
void
|
||||
_debug(const char *filename, int line, int level, const char *format, ...)
|
||||
{
|
||||
char buf[28];
|
||||
char buf[32] = {0};
|
||||
va_list vlist;
|
||||
time_t ts;
|
||||
sigset_t block_chld;
|
||||
@@ -75,7 +77,7 @@ _debug(const char *filename, int line, int level, const char *format, ...)
|
||||
}
|
||||
|
||||
if (debugconf.log_syslog) {
|
||||
openlog("wifidog", LOG_PID, debugconf.syslog_facility);
|
||||
openlog(PROGNAME, LOG_PID, debugconf.syslog_facility);
|
||||
va_start(vlist, format);
|
||||
vsyslog(level, format, vlist);
|
||||
va_end(vlist);
|
||||
|
||||
1
debug.h
1
debug.h
@@ -28,6 +28,7 @@
|
||||
#define _WIFIDOG_DEBUG_H_
|
||||
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
|
||||
|
||||
|
||||
13
docker/Dockerfile
Normal file
13
docker/Dockerfile
Normal file
@@ -0,0 +1,13 @@
|
||||
FROM alpine:3.17 AS builder
|
||||
|
||||
RUN apk update && apk add --no-cache cmake make git gcc \
|
||||
musl-dev linux-headers openssl-dev json-c-dev libevent-dev zlib-dev \
|
||||
openssl-libs-static libevent-static zlib-static
|
||||
|
||||
WORKDIR /xfrpc
|
||||
COPY . .
|
||||
WORKDIR /xfrpc/build
|
||||
RUN rm * -rf && cmake -D STATIC_BUILD=ON ../ && make
|
||||
|
||||
FROM scratch AS export-stage
|
||||
COPY --from=builder /xfrpc/build/xfrpc .
|
||||
69
frame.c
69
frame.c
@@ -1,69 +0,0 @@
|
||||
#include "frame.h"
|
||||
#include "session.h"
|
||||
#include "version.h"
|
||||
#include "common.h"
|
||||
|
||||
const static int size_of_ver = 1;
|
||||
const static int size_of_cmd = 1;
|
||||
const static int size_of_length = 2;
|
||||
const static int size_of_sid = 4;
|
||||
const static char version = 1;
|
||||
|
||||
int get_header_size() {
|
||||
return size_of_ver + size_of_cmd + size_of_length + size_of_sid;
|
||||
}
|
||||
|
||||
struct frame *new_frame(char cmd, uint32_t sid) {
|
||||
struct frame *f = calloc(sizeof(struct frame), 1);
|
||||
if (f != NULL) {
|
||||
f->ver = version;
|
||||
f->cmd = cmd;
|
||||
f->sid = sid;
|
||||
f->len = 0;
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
// f->len is rawed in this func
|
||||
struct frame *raw_frame(unsigned char *buf, const size_t buf_len)
|
||||
{
|
||||
int header_size = get_header_size();
|
||||
if (buf_len < header_size) {
|
||||
return NULL;
|
||||
}
|
||||
char ver = buf[VERI];
|
||||
char cmd = buf[CMDI];
|
||||
uint32_t sid = *(uint32_t *)(buf + SIDI);
|
||||
|
||||
struct frame *f = new_frame(cmd, sid);
|
||||
f->ver = ver;
|
||||
f->len = *(ushort *)(buf + LENI);
|
||||
f->data = buf_len > header_size ? (unsigned char *)(buf + header_size) : NULL;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
struct frame *raw_frame_only_msg(unsigned char *buf, const size_t buf_len)
|
||||
{
|
||||
struct frame *f = new_frame(0, 0);
|
||||
f->ver = CLIENT_V;
|
||||
f->len = (ushort)buf_len;
|
||||
f->data = buf;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
void set_frame_cmd(struct frame *f, char cmd)
|
||||
{
|
||||
f->cmd = cmd;
|
||||
}
|
||||
|
||||
void set_frame_len(struct frame *f, ushort data_len)
|
||||
{
|
||||
f->len = data_len;
|
||||
}
|
||||
|
||||
void free_frame(struct frame *f) {
|
||||
SAFE_FREE(f);
|
||||
}
|
||||
40
frame.h
40
frame.h
@@ -1,40 +0,0 @@
|
||||
#ifndef _FRAME_H_
|
||||
#define _FRAME_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "uthash.h"
|
||||
#include "common.h"
|
||||
|
||||
#define VERI 0
|
||||
#define CMDI 1
|
||||
#define LENI 2
|
||||
#define SIDI 4
|
||||
#define DATAI 8
|
||||
|
||||
// cmds
|
||||
enum cmd_type {
|
||||
cmdSYN = 0, // stream open
|
||||
cmdFIN, // stream close, a.k.a EOF mark
|
||||
cmdPSH, // data push
|
||||
cmdNOP, // no operation
|
||||
};
|
||||
|
||||
struct frame {
|
||||
char ver;
|
||||
char cmd;
|
||||
ushort len;
|
||||
uint32_t sid;
|
||||
unsigned char *data;
|
||||
};
|
||||
|
||||
struct frame *new_frame(char cmd, uint32_t sid);
|
||||
int get_header_size();
|
||||
struct frame *raw_frame(unsigned char *buf, const size_t buf_len);
|
||||
struct frame *raw_frame_only_msg(unsigned char *buf, const size_t buf_len);
|
||||
void set_frame_cmd(struct frame *f, char cmd);
|
||||
void set_frame_len(struct frame *f, ushort data_len);
|
||||
void free_frame(struct frame *f);
|
||||
|
||||
#endif //_FRAME_H_
|
||||
@@ -1,2 +0,0 @@
|
||||
/usr/bin/xfrp_client
|
||||
/usr/bin/xfrp_test_server
|
||||
72
login.c
72
login.c
@@ -1,3 +1,29 @@
|
||||
/* vim: set et ts=4 sts=4 sw=4 : */
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, contact: *
|
||||
* *
|
||||
* Free Software Foundation Voice: +1-617-542-5942 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
/** @file login.c
|
||||
@brief xfrpc login protocol implemented
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -15,6 +41,7 @@
|
||||
#include "msg.h"
|
||||
#include "version.h"
|
||||
#include "login.h"
|
||||
#include "utils.h"
|
||||
|
||||
static struct login *c_login;
|
||||
|
||||
@@ -37,38 +64,59 @@ void init_login()
|
||||
{
|
||||
if (! c_login)
|
||||
c_login = calloc(sizeof(struct login), 1);
|
||||
|
||||
assert(c_login);
|
||||
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
assert(c_conf);
|
||||
|
||||
|
||||
struct utsname uname_buf;
|
||||
if (uname(&uname_buf)) {
|
||||
return;
|
||||
debug(LOG_ERR, "error: get system info failed!");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
c_login->version = strdup(PROTOCOL_VERESION);
|
||||
assert(c_login->version);
|
||||
c_login->hostname = NULL;
|
||||
c_login->os = strdup(uname_buf.sysname);
|
||||
c_login->os = strdup(uname_buf.sysname);
|
||||
assert(c_login->os);
|
||||
c_login->arch = strdup(uname_buf.machine);
|
||||
assert(c_login->arch);
|
||||
c_login->user = NULL;
|
||||
|
||||
c_login->timestamp = 0;
|
||||
c_login->run_id = NULL;
|
||||
c_login->metas = NULL;
|
||||
c_login->pool_count = 1;
|
||||
c_login->privilege_key = NULL;
|
||||
c_login->user = c_conf->user;
|
||||
|
||||
c_login->logged = 0;
|
||||
|
||||
/* start to init login->run_id */
|
||||
char ifname[16] = {0};
|
||||
if(get_net_ifname(ifname, 16)){
|
||||
debug(LOG_ERR, "error: get device sign ifname failed!");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (strcmp(ifname, "br-lan") == 0 || strcmp(ifname, "br0") == 0) {
|
||||
c_conf->is_router = 1;
|
||||
debug(LOG_DEBUG, "working in router");
|
||||
}
|
||||
|
||||
char if_mac[64] = {0};
|
||||
if(get_net_mac(ifname, if_mac, sizeof(if_mac))) {
|
||||
debug(LOG_ERR, "error: Hard ware MAC address of [%s] get failed!", ifname);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
c_login->run_id = strdup(if_mac);
|
||||
assert(c_login->run_id);
|
||||
}
|
||||
|
||||
int login_resp_check(struct login_resp *lr)
|
||||
{
|
||||
debug(LOG_DEBUG, "xfrp login response: run_id: [%s], version: [%s], error: [%s]",
|
||||
lr->run_id,
|
||||
lr->version,
|
||||
lr->error);
|
||||
|
||||
if (lr->run_id == NULL || strlen(lr->run_id) <= 1) {
|
||||
if (lr->error && strlen(lr->error) > 0) {
|
||||
debug(LOG_ERR, "login response error: %s", lr->error);
|
||||
@@ -77,10 +125,14 @@ int login_resp_check(struct login_resp *lr)
|
||||
c_login->logged = 0;
|
||||
} else {
|
||||
c_login->logged = 1;
|
||||
debug(LOG_DEBUG, "xfrp login response: run_id: [%s], version: [%s]",
|
||||
lr->run_id,
|
||||
lr->version);
|
||||
SAFE_FREE(c_login->run_id);
|
||||
|
||||
c_login->run_id = strdup(lr->run_id);
|
||||
assert(c_login->run_id);
|
||||
}
|
||||
|
||||
return c_login->logged;
|
||||
}
|
||||
}
|
||||
|
||||
32
login.h
32
login.h
@@ -1,3 +1,29 @@
|
||||
/* vim: set et ts=4 sts=4 sw=4 : */
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, contact: *
|
||||
* *
|
||||
* Free Software Foundation Voice: +1-617-542-5942 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
/** @file login.h
|
||||
@brief xfrp login header
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
#ifndef _LOGIN_H_
|
||||
#define _LOGIN_H_
|
||||
|
||||
@@ -5,6 +31,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "uthash.h"
|
||||
|
||||
@@ -15,8 +42,9 @@ struct login {
|
||||
char *arch;
|
||||
char *user;
|
||||
char *privilege_key;
|
||||
long int timestamp;
|
||||
time_t timestamp;
|
||||
char *run_id;
|
||||
char *metas;
|
||||
int pool_count;
|
||||
|
||||
/* fields not need json marshal */
|
||||
@@ -35,4 +63,4 @@ struct login *get_common_login_config();
|
||||
int is_logged();
|
||||
int login_resp_check(struct login_resp *lr);
|
||||
|
||||
#endif //_LOGIN_H_
|
||||
#endif //_LOGIN_H_
|
||||
|
||||
6
main.c
6
main.c
@@ -21,10 +21,10 @@
|
||||
|
||||
/** @file main.c
|
||||
@brief xfrp client main
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liudengfeng@kunteng.org>
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
#include "xfrp_client.h"
|
||||
#include "xfrpc.h"
|
||||
#include "commandline.h"
|
||||
#include "login.h"
|
||||
|
||||
@@ -32,5 +32,5 @@ int main(int argc, char **argv)
|
||||
{
|
||||
parse_commandline(argc, argv);
|
||||
init_login();
|
||||
xfrp_client_loop();
|
||||
xfrpc_loop();
|
||||
}
|
||||
|
||||
10039
mongoose.c
Normal file
10039
mongoose.c
Normal file
File diff suppressed because it is too large
Load Diff
1915
mongoose.h
Normal file
1915
mongoose.h
Normal file
File diff suppressed because it is too large
Load Diff
511
msg.c
511
msg.c
@@ -20,14 +20,13 @@
|
||||
\********************************************************************/
|
||||
|
||||
/** @file msg.c
|
||||
@brief xfrp client msg related
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liudengfeng@kunteng.org>
|
||||
@brief xfrpc client msg related
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <json-c/json.h>
|
||||
#include <json-c/bits.h>
|
||||
#include <openssl/md5.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
@@ -35,78 +34,90 @@
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "msg.h"
|
||||
#include "const.h"
|
||||
#include "config.h"
|
||||
#include "frame.h"
|
||||
#include "debug.h"
|
||||
#include "common.h"
|
||||
#include "login.h"
|
||||
#include "client.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define JSON_MARSHAL_TYPE(jobj,key,jtype,item) \
|
||||
json_object_object_add(jobj, key, json_object_new_##jtype((item)));
|
||||
#define JSON_MARSHAL_TYPE(jobj, key, jtype, item) \
|
||||
json_object_object_add(jobj, key, json_object_new_##jtype((item)));
|
||||
|
||||
#define SAFE_JSON_STRING(str_target) \
|
||||
str_target?str_target:"\0"
|
||||
str_target ? str_target : "\0"
|
||||
|
||||
const char msg_typs[] = {TypeLogin, TypeLoginResp, TypeNewProxy, TypeNewProxyResp,
|
||||
TypeNewWorkConn, TypeReqWorkConn, TypeStartWorkConn, TypePing, TypePong, TypeUdpPacket};
|
||||
const char msg_types[] = {TypeLogin,
|
||||
TypeLoginResp,
|
||||
TypeNewProxy,
|
||||
TypeNewProxyResp,
|
||||
TypeNewWorkConn,
|
||||
TypeReqWorkConn,
|
||||
TypeStartWorkConn,
|
||||
TypePing,
|
||||
TypePong,
|
||||
TypeUDPPacket};
|
||||
|
||||
char *calc_md5(const char *data, int datalen)
|
||||
char *
|
||||
calc_md5(const char *data, int datalen)
|
||||
{
|
||||
unsigned char digest[16] = {0};
|
||||
char *out = (char*)malloc(33);
|
||||
char *out = (char *)malloc(33);
|
||||
assert(out);
|
||||
|
||||
MD5_CTX md5;
|
||||
|
||||
|
||||
MD5_Init(&md5);
|
||||
MD5_Update(&md5, data, datalen);
|
||||
MD5_Final(digest, &md5);
|
||||
|
||||
for (int n = 0; n < 16; ++n) {
|
||||
snprintf(&(out[n*2]), 3, "%02x", (unsigned int)digest[n]);
|
||||
}
|
||||
|
||||
return out;
|
||||
for (int n = 0; n < 16; ++n)
|
||||
{
|
||||
snprintf(&(out[n * 2]), 3, "%02x", (unsigned int)digest[n]);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static void fill_custom_domains(struct json_object *j_ctl_req, const char *custom_domains)
|
||||
static void
|
||||
fill_custom_domains(struct json_object *j_ctl_req, const char *custom_domains)
|
||||
{
|
||||
struct json_object *jarray_cdomains = json_object_new_array();
|
||||
assert(jarray_cdomains);
|
||||
char *tmp = strdup(custom_domains);
|
||||
assert(tmp);
|
||||
char *tok = tmp, *end = tmp;
|
||||
while (tok != NULL) {
|
||||
while (tok != NULL)
|
||||
{
|
||||
strsep(&end, ",");
|
||||
json_object_array_add(jarray_cdomains, json_object_new_string(tok));
|
||||
|
||||
int dname_len = strlen(tok) + 1;
|
||||
char *dname_buf = (char *)calloc(1, dname_len);
|
||||
assert(dname_buf);
|
||||
dns_unified(tok, dname_buf, dname_len);
|
||||
json_object_array_add(jarray_cdomains, json_object_new_string(dname_buf));
|
||||
|
||||
free(dname_buf);
|
||||
tok = end;
|
||||
}
|
||||
SAFE_FREE(tmp);
|
||||
|
||||
|
||||
json_object_object_add(j_ctl_req, "custom_domains", jarray_cdomains);
|
||||
}
|
||||
|
||||
// NEED FREE
|
||||
struct message *new_message() {
|
||||
struct message *msg = calloc(1, sizeof(struct message)); //TODO: FREE
|
||||
if (msg)
|
||||
{
|
||||
msg->data_p = NULL;
|
||||
msg->data_len = 0;
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
struct work_conn *new_work_conn() {
|
||||
struct work_conn *
|
||||
new_work_conn()
|
||||
{
|
||||
struct work_conn *work_c = calloc(1, sizeof(struct work_conn));
|
||||
if (work_c)
|
||||
assert(work_c);
|
||||
if (work_c)
|
||||
work_c->run_id = NULL;
|
||||
|
||||
return work_c;
|
||||
}
|
||||
|
||||
char *get_auth_key(const char *token, long int *timestamp)
|
||||
char *
|
||||
get_auth_key(const char *token, long int *timestamp)
|
||||
{
|
||||
char seed[128] = {0};
|
||||
*timestamp = time(NULL);
|
||||
@@ -114,26 +125,30 @@ char *get_auth_key(const char *token, long int *timestamp)
|
||||
snprintf(seed, 128, "%s%ld", token, *timestamp);
|
||||
else
|
||||
snprintf(seed, 128, "%ld", *timestamp);
|
||||
|
||||
|
||||
return calc_md5(seed, strlen(seed));
|
||||
}
|
||||
|
||||
size_t login_request_marshal(char **msg)
|
||||
size_t
|
||||
login_request_marshal(char **msg)
|
||||
{
|
||||
size_t nret = 0;
|
||||
struct json_object *j_login_req = json_object_new_object();
|
||||
if (is_error(j_login_req))
|
||||
if (j_login_req == NULL)
|
||||
return 0;
|
||||
|
||||
|
||||
struct login *lg = get_common_login_config();
|
||||
if (!lg)
|
||||
if (!lg) {
|
||||
json_object_put(j_login_req);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
SAFE_FREE(lg->privilege_key);
|
||||
struct common_conf *cf = get_common_config();
|
||||
char *auth_key = get_auth_key(cf->privilege_token, &lg->timestamp);
|
||||
char *auth_key = get_auth_key(cf->auth_token, &lg->timestamp);
|
||||
lg->privilege_key = strdup(auth_key);
|
||||
|
||||
assert(lg->privilege_key);
|
||||
|
||||
JSON_MARSHAL_TYPE(j_login_req, "version", string, lg->version);
|
||||
JSON_MARSHAL_TYPE(j_login_req, "hostname", string, SAFE_JSON_STRING(lg->hostname));
|
||||
JSON_MARSHAL_TYPE(j_login_req, "os", string, lg->os);
|
||||
@@ -141,15 +156,21 @@ size_t login_request_marshal(char **msg)
|
||||
JSON_MARSHAL_TYPE(j_login_req, "user", string, SAFE_JSON_STRING(lg->user));
|
||||
|
||||
JSON_MARSHAL_TYPE(j_login_req, "privilege_key", string, SAFE_JSON_STRING(lg->privilege_key));
|
||||
JSON_MARSHAL_TYPE(j_login_req, "timestamp", int64, lg->timestamp);
|
||||
if (sizeof(time_t) == 4) {
|
||||
JSON_MARSHAL_TYPE(j_login_req, "timestamp", int, lg->timestamp);
|
||||
} else {
|
||||
JSON_MARSHAL_TYPE(j_login_req, "timestamp", int64, lg->timestamp);
|
||||
}
|
||||
JSON_MARSHAL_TYPE(j_login_req, "run_id", string, SAFE_JSON_STRING(lg->run_id));
|
||||
JSON_MARSHAL_TYPE(j_login_req, "pool_count", int, lg->pool_count);
|
||||
json_object_object_add(j_login_req, "metas", NULL);
|
||||
|
||||
const char *tmp = NULL;
|
||||
tmp = json_object_to_json_string(j_login_req);
|
||||
if (tmp && strlen(tmp) > 0) {
|
||||
nret = strlen(tmp);
|
||||
*msg = strdup(tmp);
|
||||
assert(*msg);
|
||||
}
|
||||
json_object_put(j_login_req);
|
||||
SAFE_FREE(auth_key);
|
||||
@@ -159,21 +180,52 @@ size_t login_request_marshal(char **msg)
|
||||
int new_proxy_service_marshal(const struct proxy_service *np_req, char **msg)
|
||||
{
|
||||
const char *tmp = NULL;
|
||||
int nret = 0;
|
||||
int nret = 0;
|
||||
char *path = NULL;
|
||||
char *delimiter = ",";
|
||||
char *save = NULL;
|
||||
struct json_object *j_np_req = json_object_new_object();
|
||||
if ( ! j_np_req)
|
||||
if (!j_np_req)
|
||||
return 0;
|
||||
|
||||
|
||||
JSON_MARSHAL_TYPE(j_np_req, "proxy_name", string, np_req->proxy_name);
|
||||
JSON_MARSHAL_TYPE(j_np_req, "proxy_type", string, np_req->proxy_type);
|
||||
// if proxy_type is socks5, set the proxy_type to tcp
|
||||
if (strcmp(np_req->proxy_type, "socks5") == 0 || strcmp(np_req->proxy_type, "mstsc") == 0) {
|
||||
JSON_MARSHAL_TYPE(j_np_req, "proxy_type", string, "tcp");
|
||||
} else {
|
||||
JSON_MARSHAL_TYPE(j_np_req, "proxy_type", string, np_req->proxy_type);
|
||||
}
|
||||
JSON_MARSHAL_TYPE(j_np_req, "use_encryption", boolean, np_req->use_encryption);
|
||||
JSON_MARSHAL_TYPE(j_np_req, "use_compression", boolean, np_req->use_compression);
|
||||
JSON_MARSHAL_TYPE(j_np_req, "remote_port", int, np_req->remote_port);
|
||||
|
||||
// if proxy_type is tcp, http, https and socks5, set group and group_key to j_np_req
|
||||
if (strcmp(np_req->proxy_type, "tcp") == 0 ||
|
||||
strcmp(np_req->proxy_type, "http") == 0 ||
|
||||
strcmp(np_req->proxy_type, "https") == 0 ||
|
||||
strcmp(np_req->proxy_type, "socks5") == 0) {
|
||||
|
||||
if (np_req->group) {
|
||||
JSON_MARSHAL_TYPE(j_np_req, "group", string, np_req->group);
|
||||
}
|
||||
if (np_req->group_key) {
|
||||
JSON_MARSHAL_TYPE(j_np_req, "group_key", string, np_req->group_key);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_ftp_proxy(np_req)) {
|
||||
JSON_MARSHAL_TYPE(j_np_req, "remote_data_port", int, np_req->remote_data_port);
|
||||
}
|
||||
|
||||
if (np_req->custom_domains) {
|
||||
fill_custom_domains(j_np_req, np_req->custom_domains);
|
||||
json_object_object_add(j_np_req, "remote_port", NULL);
|
||||
} else {
|
||||
json_object_object_add(j_np_req, "custom_domains", NULL);
|
||||
if (np_req->remote_port != -1) {
|
||||
JSON_MARSHAL_TYPE(j_np_req, "remote_port", int, np_req->remote_port);
|
||||
} else {
|
||||
json_object_object_add(j_np_req, "remote_port", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
JSON_MARSHAL_TYPE(j_np_req, "subdomain", string, SAFE_JSON_STRING(np_req->subdomain));
|
||||
@@ -181,18 +233,24 @@ int new_proxy_service_marshal(const struct proxy_service *np_req, char **msg)
|
||||
json_object *j_location_array = json_object_new_array();
|
||||
if (np_req->locations) {
|
||||
json_object_object_add(j_np_req, "locations", j_location_array);
|
||||
path = strtok_r(np_req->locations, delimiter, &save);
|
||||
while (path) {
|
||||
json_object_array_add(j_location_array, json_object_new_string(path));
|
||||
path = strtok_r(NULL, delimiter, &save);
|
||||
}
|
||||
} else {
|
||||
json_object_object_add(j_np_req, "locations", NULL);
|
||||
}
|
||||
|
||||
|
||||
JSON_MARSHAL_TYPE(j_np_req, "host_header_rewrite", string, SAFE_JSON_STRING(np_req->host_header_rewrite));
|
||||
JSON_MARSHAL_TYPE(j_np_req, "http_user", string, SAFE_JSON_STRING(np_req->http_user));
|
||||
JSON_MARSHAL_TYPE(j_np_req, "http_pwd", string, SAFE_JSON_STRING(np_req->http_pwd));
|
||||
|
||||
|
||||
tmp = json_object_to_json_string(j_np_req);
|
||||
if (tmp && strlen(tmp) > 0) {
|
||||
nret = strlen(tmp);
|
||||
*msg = strdup(tmp);
|
||||
assert(*msg);
|
||||
}
|
||||
json_object_put(j_np_req);
|
||||
|
||||
@@ -204,7 +262,7 @@ int new_work_conn_marshal(const struct work_conn *work_c, char **msg)
|
||||
const char *tmp = NULL;
|
||||
int nret = 0;
|
||||
struct json_object *j_new_work_conn = json_object_new_object();
|
||||
if (! j_new_work_conn)
|
||||
if (!j_new_work_conn)
|
||||
return 0;
|
||||
|
||||
JSON_MARSHAL_TYPE(j_new_work_conn, "run_id", string, SAFE_JSON_STRING(work_c->run_id));
|
||||
@@ -212,6 +270,7 @@ int new_work_conn_marshal(const struct work_conn *work_c, char **msg)
|
||||
if (tmp && strlen(tmp) > 0) {
|
||||
nret = strlen(tmp);
|
||||
*msg = strdup(tmp);
|
||||
assert(*msg);
|
||||
}
|
||||
|
||||
json_object_put(j_new_work_conn);
|
||||
@@ -219,158 +278,344 @@ int new_work_conn_marshal(const struct work_conn *work_c, char **msg)
|
||||
return nret;
|
||||
}
|
||||
|
||||
// login_resp_unmarshal NEED FREE
|
||||
struct login_resp *login_resp_unmarshal(const char *jres)
|
||||
// result returned of this func need be free
|
||||
struct new_proxy_response *
|
||||
new_proxy_resp_unmarshal(const char *jres)
|
||||
{
|
||||
struct json_object *j_lg_res = json_tokener_parse(jres);
|
||||
if (is_error(j_lg_res))
|
||||
struct json_object *j_np_res = json_tokener_parse(jres);
|
||||
if (j_np_res == NULL)
|
||||
return NULL;
|
||||
|
||||
struct login_resp *lr = calloc(1, sizeof(struct login_resp));
|
||||
if (lr == NULL) {
|
||||
|
||||
struct new_proxy_response *npr = calloc(1, sizeof(struct new_proxy_response));
|
||||
assert(npr);
|
||||
|
||||
struct json_object *npr_run_id = NULL;
|
||||
if (json_object_object_get_ex(j_np_res, "run_id", &npr_run_id))
|
||||
npr->run_id = strdup(json_object_get_string(npr_run_id));
|
||||
|
||||
struct json_object *npr_proxy_remote_addr = NULL;
|
||||
if (!json_object_object_get_ex(j_np_res, "remote_addr", &npr_proxy_remote_addr)) {
|
||||
free(npr->run_id);
|
||||
free(npr);
|
||||
npr = NULL;
|
||||
goto END_ERROR;
|
||||
}
|
||||
|
||||
struct json_object *l_version = NULL;
|
||||
if (! json_object_object_get_ex(j_lg_res, "version", &l_version))
|
||||
const char *remote_addr = json_object_get_string(npr_proxy_remote_addr);
|
||||
char *port = strrchr(remote_addr, ':');
|
||||
if (port) {
|
||||
port++;
|
||||
npr->remote_port = atoi(port);
|
||||
}
|
||||
|
||||
struct json_object *npr_proxy_name = NULL;
|
||||
if (!json_object_object_get_ex(j_np_res, "proxy_name", &npr_proxy_name)) {
|
||||
free(npr->run_id);
|
||||
free(npr);
|
||||
npr = NULL;
|
||||
goto END_ERROR;
|
||||
}
|
||||
|
||||
npr->proxy_name = strdup(json_object_get_string(npr_proxy_name));
|
||||
assert(npr->proxy_name);
|
||||
|
||||
struct json_object *npr_error = NULL;
|
||||
if (!json_object_object_get_ex(j_np_res, "error", &npr_error)) {
|
||||
free(npr->run_id);
|
||||
free(npr->proxy_name);
|
||||
free(npr);
|
||||
npr = NULL;
|
||||
goto END_ERROR;
|
||||
}
|
||||
npr->error = strdup(json_object_get_string(npr_error));
|
||||
assert(npr->error);
|
||||
|
||||
END_ERROR:
|
||||
json_object_put(j_np_res);
|
||||
return npr;
|
||||
}
|
||||
|
||||
// login_resp_unmarshal NEED FREE
|
||||
struct login_resp *
|
||||
login_resp_unmarshal(const char *jres)
|
||||
{
|
||||
struct json_object *j_lg_res = json_tokener_parse(jres);
|
||||
if (j_lg_res == NULL)
|
||||
return NULL;
|
||||
|
||||
struct login_resp *lr = calloc(1, sizeof(struct login_resp));
|
||||
assert(lr);
|
||||
|
||||
struct json_object *l_version = NULL;
|
||||
if (!json_object_object_get_ex(j_lg_res, "version", &l_version)) {
|
||||
free(lr);
|
||||
lr = NULL;
|
||||
goto END_ERROR;
|
||||
}
|
||||
|
||||
lr->version = strdup(json_object_get_string(l_version));
|
||||
assert(lr->version);
|
||||
|
||||
struct json_object *l_run_id = NULL;
|
||||
if (! json_object_object_get_ex(j_lg_res, "run_id", &l_run_id))
|
||||
if (!json_object_object_get_ex(j_lg_res, "run_id", &l_run_id)) {
|
||||
free(lr->version);
|
||||
free(lr);
|
||||
lr = NULL;
|
||||
goto END_ERROR;
|
||||
lr->run_id = strdup(json_object_get_string(l_run_id));
|
||||
}
|
||||
|
||||
lr->run_id = strdup(json_object_get_string(l_run_id));
|
||||
assert(lr->run_id);
|
||||
|
||||
struct json_object *l_error = NULL;
|
||||
if(! json_object_object_get_ex(j_lg_res, "error", &l_error))
|
||||
if (!json_object_object_get_ex(j_lg_res, "error", &l_error)) {
|
||||
free(lr->version);
|
||||
free(lr->run_id);
|
||||
free(lr);
|
||||
lr = NULL;
|
||||
goto END_ERROR;
|
||||
}
|
||||
|
||||
lr->error = strdup(json_object_get_string(l_error));
|
||||
assert(lr->error);
|
||||
|
||||
END_ERROR:
|
||||
json_object_put(j_lg_res);
|
||||
return lr;
|
||||
}
|
||||
|
||||
struct start_work_conn_resp *start_work_conn_resp_unmarshal(const char *resp_msg)
|
||||
struct start_work_conn_resp *
|
||||
start_work_conn_resp_unmarshal(const char *resp_msg)
|
||||
{
|
||||
struct json_object *j_start_w_res = json_tokener_parse(resp_msg);
|
||||
if (is_error(j_start_w_res))
|
||||
if (j_start_w_res == NULL)
|
||||
return NULL;
|
||||
|
||||
struct start_work_conn_resp *sr = calloc(1, sizeof(struct start_work_conn_resp));
|
||||
if (! sr)
|
||||
goto START_W_C_R_END;
|
||||
assert(sr);
|
||||
|
||||
struct json_object *pn = NULL;
|
||||
if(! json_object_object_get_ex(j_start_w_res, "proxy_name", &pn))
|
||||
if (!json_object_object_get_ex(j_start_w_res, "proxy_name", &pn)) {
|
||||
free(sr);
|
||||
sr = NULL;
|
||||
goto START_W_C_R_END;
|
||||
}
|
||||
|
||||
sr->proxy_name = strdup(json_object_get_string(pn));
|
||||
assert(sr->proxy_name);
|
||||
|
||||
START_W_C_R_END:
|
||||
json_object_put(j_start_w_res);
|
||||
return sr;
|
||||
}
|
||||
|
||||
struct control_response *control_response_unmarshal(const char *jres)
|
||||
struct control_response *
|
||||
control_response_unmarshal(const char *jres)
|
||||
{
|
||||
struct json_object *j_ctl_res = json_tokener_parse(jres);
|
||||
if (is_error(j_ctl_res))
|
||||
if (j_ctl_res == NULL)
|
||||
return NULL;
|
||||
struct control_response *ctl_res = calloc(sizeof(struct control_response), 1);
|
||||
if (ctl_res == NULL) {
|
||||
assert(ctl_res);
|
||||
|
||||
struct json_object *jtype = NULL;
|
||||
if (!json_object_object_get_ex(j_ctl_res, "type", &jtype)) {
|
||||
free(ctl_res);
|
||||
ctl_res = NULL;
|
||||
goto END_ERROR;
|
||||
}
|
||||
|
||||
struct json_object *jtype = NULL;
|
||||
if(! json_object_object_get_ex(j_ctl_res, "type", &jtype))
|
||||
goto END_ERROR;
|
||||
ctl_res->type = json_object_get_int(jtype);
|
||||
|
||||
|
||||
struct json_object *jcode = NULL;
|
||||
if(! json_object_object_get_ex(j_ctl_res, "code", &jcode))
|
||||
if (!json_object_object_get_ex(j_ctl_res, "code", &jcode)) {
|
||||
free(ctl_res);
|
||||
ctl_res = NULL;
|
||||
goto END_ERROR;
|
||||
}
|
||||
|
||||
ctl_res->code = json_object_get_int(jcode);
|
||||
|
||||
|
||||
struct json_object *jmsg = NULL;
|
||||
if(json_object_object_get_ex(j_ctl_res, "msg", &jmsg))
|
||||
ctl_res->msg = strdup(json_object_get_string(jmsg));
|
||||
|
||||
if (!json_object_object_get_ex(j_ctl_res, "msg", &jmsg)) {
|
||||
free(ctl_res);
|
||||
ctl_res = NULL;
|
||||
goto END_ERROR;
|
||||
}
|
||||
ctl_res->msg = strdup(json_object_get_string(jmsg));
|
||||
assert(ctl_res->msg);
|
||||
|
||||
END_ERROR:
|
||||
json_object_put(j_ctl_res);
|
||||
return ctl_res;
|
||||
}
|
||||
|
||||
void control_response_free(struct control_response *res)
|
||||
void
|
||||
control_response_free(struct control_response *res)
|
||||
{
|
||||
if (!res)
|
||||
return;
|
||||
|
||||
|
||||
SAFE_FREE(res->msg);
|
||||
SAFE_FREE(res);
|
||||
}
|
||||
|
||||
int msg_type_valid_check(char msg_type)
|
||||
// marshal udp packet msg
|
||||
int
|
||||
new_udp_packet_marshal(const struct udp_packet *udp, char **msg)
|
||||
{
|
||||
int i = 0;
|
||||
for(i = 0; i<(sizeof(msg_typs) / sizeof(*msg_typs)); i++) {
|
||||
if (msg_typs[i] == msg_type)
|
||||
return 1;
|
||||
// parse struct udp_packet to json
|
||||
struct json_object *j_udp = json_object_new_object();
|
||||
assert(j_udp);
|
||||
|
||||
struct json_object *content = json_object_new_string(udp->content);
|
||||
assert(content);
|
||||
json_object_object_add(j_udp, "c", content);
|
||||
|
||||
if (udp->laddr) {
|
||||
// laddr is a struct, parse it to json object and add to j_udp
|
||||
struct json_object *j_laddr = json_object_new_object();
|
||||
assert(j_laddr);
|
||||
struct json_object *j_laddr_addr = json_object_new_string(udp->laddr->addr);
|
||||
assert(j_laddr_addr);
|
||||
json_object_object_add(j_laddr, "IP", j_laddr_addr);
|
||||
struct json_object *j_laddr_port = json_object_new_int(udp->laddr->port);
|
||||
assert(j_laddr_port);
|
||||
json_object_object_add(j_laddr, "Port", j_laddr_port);
|
||||
json_object_object_add(j_udp, "l", j_laddr);
|
||||
json_object *j_laddr_zone = json_object_new_string("");
|
||||
assert(j_laddr_zone);
|
||||
json_object_object_add(j_laddr, "Zone", j_laddr_zone);
|
||||
} else {
|
||||
// laddr is NULL, add null to j_udp
|
||||
struct json_object *j_laddr = json_object_new_object();
|
||||
assert(j_laddr);
|
||||
json_object_object_add(j_udp, "l", j_laddr);
|
||||
}
|
||||
|
||||
if (udp->raddr) {
|
||||
// raddr is a struct, parse it to json object and add to j_udp
|
||||
struct json_object *j_raddr = json_object_new_object();
|
||||
assert(j_raddr);
|
||||
struct json_object *j_raddr_addr = json_object_new_string(udp->raddr->addr);
|
||||
assert(j_raddr_addr);
|
||||
json_object_object_add(j_raddr, "IP", j_raddr_addr);
|
||||
struct json_object *j_raddr_port = json_object_new_int(udp->raddr->port);
|
||||
assert(j_raddr_port);
|
||||
json_object_object_add(j_raddr, "Port", j_raddr_port);
|
||||
json_object_object_add(j_udp, "r", j_raddr);
|
||||
json_object *j_raddr_zone = json_object_new_string("");
|
||||
assert(j_raddr_zone);
|
||||
json_object_object_add(j_raddr, "Zone", j_raddr_zone);
|
||||
} else {
|
||||
// raddr is NULL, add null to j_udp
|
||||
struct json_object *j_raddr = json_object_new_object();
|
||||
assert(j_raddr);
|
||||
json_object_object_add(j_udp, "r", j_raddr);
|
||||
}
|
||||
|
||||
// convert json to string msg
|
||||
*msg = strdup(json_object_to_json_string(j_udp));
|
||||
assert(*msg);
|
||||
json_object_put(j_udp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// only handle recved message with right message type
|
||||
struct message *unpack(unsigned char *recv_msg, const ushort len)
|
||||
void
|
||||
udp_packet_free(struct udp_packet *udp)
|
||||
{
|
||||
struct message *msg = new_message();
|
||||
msg->type = *(recv_msg + MSG_TYPE_I);
|
||||
if (!udp)
|
||||
return;
|
||||
|
||||
if (! msg_type_valid_check(msg->type) ) {
|
||||
debug(LOG_ERR, "message recved type is invalid!");
|
||||
return NULL;
|
||||
}
|
||||
SAFE_FREE(udp->content);
|
||||
SAFE_FREE(udp->laddr->addr);
|
||||
SAFE_FREE(udp->laddr->zone);
|
||||
SAFE_FREE(udp->laddr);
|
||||
SAFE_FREE(udp->raddr->addr);
|
||||
SAFE_FREE(udp->raddr->zone);
|
||||
SAFE_FREE(udp->raddr);
|
||||
|
||||
msg_size_t data_len_bigend;
|
||||
data_len_bigend = *(msg_size_t *)(recv_msg + MSG_LEN_I);
|
||||
msg->data_len = msg_ntoh(data_len_bigend);
|
||||
|
||||
if (msg->data_len > 0) {
|
||||
msg->data_p = calloc(msg->data_len + 1, 1);
|
||||
assert(msg->data_p);
|
||||
|
||||
memcpy(msg->data_p, recv_msg + MSG_DATA_I, msg->data_len);
|
||||
}
|
||||
|
||||
return msg;
|
||||
SAFE_FREE(udp);
|
||||
}
|
||||
|
||||
size_t pack(struct message *req_msg, unsigned char **ret_buf)
|
||||
// unmarshal udp packet msg
|
||||
struct udp_packet *
|
||||
udp_packet_unmarshal(const char *msg)
|
||||
{
|
||||
int endian_check = 1;
|
||||
// little endian if true
|
||||
struct json_object *j_udp = json_tokener_parse(msg);
|
||||
if (j_udp == NULL)
|
||||
return NULL;
|
||||
struct udp_packet *udp = calloc(sizeof(struct udp_packet), 1);
|
||||
assert(udp);
|
||||
|
||||
msg_size_t data_len_bigend;
|
||||
if(*(char *)&endian_check == 1)
|
||||
data_len_bigend = msg_hton(req_msg->data_len);
|
||||
else
|
||||
data_len_bigend = req_msg->data_len;
|
||||
|
||||
|
||||
size_t buf_len = TYPE_LEN + sizeof(data_len_bigend) + req_msg->data_len;
|
||||
*ret_buf = calloc(buf_len, 1);
|
||||
|
||||
if (*ret_buf == NULL) {
|
||||
return 0;
|
||||
struct json_object *j_content = NULL;
|
||||
if (!json_object_object_get_ex(j_udp, "c", &j_content)) {
|
||||
goto END_ERROR;
|
||||
}
|
||||
|
||||
udp->content = strdup(json_object_get_string(j_content));
|
||||
assert(udp->content);
|
||||
|
||||
*(*ret_buf + MSG_TYPE_I) = req_msg->type;
|
||||
*(msg_size_t *)(*ret_buf + MSG_LEN_I) = data_len_bigend;
|
||||
snprintf((char *)*ret_buf + TYPE_LEN + sizeof(data_len_bigend),
|
||||
req_msg->data_len + 1,
|
||||
"%s",
|
||||
req_msg->data_p);
|
||||
struct json_object *j_laddr = NULL;
|
||||
if (!json_object_object_get_ex(j_udp, "l", &j_laddr)) {
|
||||
goto END_ERROR;
|
||||
}
|
||||
|
||||
struct json_object *j_laddr_ip = NULL;
|
||||
if (!json_object_object_get_ex(j_laddr, "IP", &j_laddr_ip)) {
|
||||
goto END_ERROR;
|
||||
}
|
||||
struct json_object *j_laddr_port = NULL;
|
||||
if (!json_object_object_get_ex(j_laddr, "Port", &j_laddr_port)) {
|
||||
goto END_ERROR;
|
||||
}
|
||||
|
||||
struct json_object *j_laddr_zone = NULL;
|
||||
if (!json_object_object_get_ex(j_laddr, "Zone", &j_laddr_zone)) {
|
||||
goto END_ERROR;
|
||||
}
|
||||
|
||||
udp->laddr = calloc(sizeof(struct udp_addr), 1);
|
||||
assert(udp->laddr);
|
||||
udp->laddr->addr = strdup(json_object_get_string(j_laddr_ip));
|
||||
assert(udp->laddr->addr);
|
||||
udp->laddr->port = json_object_get_int(j_laddr_port);
|
||||
udp->laddr->zone = strdup(json_object_get_string(j_laddr_zone));
|
||||
assert(udp->laddr->zone);
|
||||
|
||||
return buf_len;
|
||||
struct json_object *j_raddr = NULL;
|
||||
if (!json_object_object_get_ex(j_udp, "r", &j_raddr)) {
|
||||
goto END_ERROR;
|
||||
}
|
||||
|
||||
struct json_object *j_raddr_ip = NULL;
|
||||
if (!json_object_object_get_ex(j_raddr, "IP", &j_raddr_ip)) {
|
||||
goto END_ERROR;
|
||||
}
|
||||
|
||||
struct json_object *j_raddr_port = NULL;
|
||||
if (!json_object_object_get_ex(j_raddr, "Port", &j_raddr_port)) {
|
||||
goto END_ERROR;
|
||||
}
|
||||
|
||||
struct json_object *j_raddr_zone = NULL;
|
||||
if (!json_object_object_get_ex(j_raddr, "Zone", &j_raddr_zone)) {
|
||||
goto END_ERROR;
|
||||
}
|
||||
|
||||
udp->raddr = calloc(sizeof(struct udp_addr), 1);
|
||||
assert(udp->raddr);
|
||||
udp->raddr->addr = strdup(json_object_get_string(j_raddr_ip));
|
||||
assert(udp->raddr->addr);
|
||||
udp->raddr->port = json_object_get_int(j_raddr_port);
|
||||
udp->raddr->zone = strdup(json_object_get_string(j_raddr_zone));
|
||||
assert(udp->raddr->zone);
|
||||
|
||||
json_object_put(j_udp);
|
||||
return udp;
|
||||
|
||||
END_ERROR:
|
||||
json_object_put(j_udp);
|
||||
udp_packet_free(udp);
|
||||
return NULL;
|
||||
}
|
||||
104
msg.h
104
msg.h
@@ -20,8 +20,8 @@
|
||||
\********************************************************************/
|
||||
|
||||
/** @file msg.h
|
||||
@brief xfrp msg struct
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liudengfeng@kunteng.org>
|
||||
@brief xfrpc msg struct
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
#ifndef _MSG_H_
|
||||
@@ -40,81 +40,82 @@
|
||||
|
||||
#define MSG_TYPE_I 0
|
||||
#define MSG_LEN_I 1
|
||||
#define MSG_DATA_I 5
|
||||
#define MSG_DATA_I 9
|
||||
|
||||
// msg_type match frp v0.10.0
|
||||
enum msg_type {
|
||||
TypeLogin = 'o',
|
||||
TypeLoginResp = '1',
|
||||
TypeNewProxy = 'p',
|
||||
TypeNewProxyResp = '2',
|
||||
TypeNewWorkConn = 'w',
|
||||
TypeReqWorkConn = 'r',
|
||||
TypeStartWorkConn = 's',
|
||||
TypePing = 'h',
|
||||
TypePong = '4',
|
||||
TypeUdpPacket = 'u',
|
||||
TypeLogin = 'o',
|
||||
TypeLoginResp = '1',
|
||||
TypeNewProxy = 'p',
|
||||
TypeNewProxyResp = '2',
|
||||
TypeCloseProxy = 'c',
|
||||
TypeNewWorkConn = 'w',
|
||||
TypeReqWorkConn = 'r',
|
||||
TypeStartWorkConn = 's',
|
||||
TypeNewVisitorConn = 'v',
|
||||
TypeNewVisitorConnResp = '3',
|
||||
TypePing = 'h',
|
||||
TypePong = '4',
|
||||
TypeUDPPacket = 'u',
|
||||
TypeNatHoleVisitor = 'i',
|
||||
TypeNatHoleClient = 'n',
|
||||
TypeNatHoleResp = 'm',
|
||||
TypeNatHoleClientDetectOK = 'd',
|
||||
TypeNatHoleSid = '5',
|
||||
};
|
||||
|
||||
struct general_response {
|
||||
int code;
|
||||
int code;
|
||||
char *msg;
|
||||
};
|
||||
|
||||
// messages between control connections of frpc and frps
|
||||
struct control_request {
|
||||
int type;
|
||||
char *proxy_name;
|
||||
char *auth_key;
|
||||
int use_encryption;
|
||||
int use_gzip;
|
||||
int pool_count;
|
||||
|
||||
int privilege_mode;
|
||||
char *privilege_key;
|
||||
char *proxy_type;
|
||||
int remote_port;
|
||||
char *custom_domains;
|
||||
char *locations;
|
||||
char *host_header_rewrite;
|
||||
char *http_username;
|
||||
char *http_password;
|
||||
char *subdomain;
|
||||
long timestamp;
|
||||
};
|
||||
|
||||
|
||||
struct control_response {
|
||||
int type;
|
||||
int code;
|
||||
int type;
|
||||
int code;
|
||||
char *msg;
|
||||
};
|
||||
|
||||
struct new_proxy_response {
|
||||
char *run_id;
|
||||
char *proxy_name;
|
||||
char *error;
|
||||
int remote_port;
|
||||
};
|
||||
|
||||
struct work_conn {
|
||||
char *run_id;
|
||||
};
|
||||
|
||||
struct message {
|
||||
char type;
|
||||
char *data_p;
|
||||
size_t data_len;
|
||||
struct udp_addr {
|
||||
char *addr;
|
||||
int port;
|
||||
char *zone;
|
||||
};
|
||||
|
||||
struct udp_packet {
|
||||
char *content; // base64
|
||||
struct udp_addr *laddr;
|
||||
struct udp_addr *raddr;
|
||||
};
|
||||
|
||||
struct __attribute__((__packed__)) msg_hdr {
|
||||
char type;
|
||||
uint64_t length;
|
||||
uint8_t data[];
|
||||
};
|
||||
|
||||
struct start_work_conn_resp {
|
||||
char *proxy_name;
|
||||
};
|
||||
|
||||
int new_udp_packet_marshal(const struct udp_packet *udp, char **msg);
|
||||
int new_proxy_service_marshal(const struct proxy_service *np_req, char **msg);
|
||||
int msg_type_valid_check(char msg_type);
|
||||
struct message *new_message();
|
||||
char *calc_md5(const char *data, int datalen);
|
||||
char *get_auth_key(const char *token, long int *timestamp);
|
||||
size_t login_request_marshal(char **msg);
|
||||
size_t pack(struct message *req_msg, unsigned char **ret_buf);
|
||||
struct message *unpack(unsigned char *recv_msg, const ushort len);
|
||||
|
||||
// tranlate control request to json string
|
||||
int control_request_marshal(const struct control_request *req, char **msg);
|
||||
struct new_proxy_response *new_proxy_resp_unmarshal(const char *jres);
|
||||
struct login_resp *login_resp_unmarshal(const char *jres);
|
||||
struct start_work_conn_resp *start_work_conn_resp_unmarshal(const char *resp_msg);
|
||||
|
||||
@@ -123,6 +124,11 @@ struct control_response *control_response_unmarshal(const char *jres);
|
||||
struct work_conn *new_work_conn();
|
||||
int new_work_conn_marshal(const struct work_conn *work_c, char **msg);
|
||||
|
||||
// parse json string to udp packet
|
||||
struct udp_packet *udp_packet_unmarshal(const char *jres);
|
||||
|
||||
void udp_packet_free(struct udp_packet *udp);
|
||||
|
||||
void control_response_free(struct control_response *res);
|
||||
|
||||
#endif //_MSG_H_
|
||||
#endif //_MSG_H_
|
||||
|
||||
12
pkg/debian/rules
Normal file
12
pkg/debian/rules
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/make -f
|
||||
export DEB_LDFLAGS_MAINT_APPEND=-Wl,-O1
|
||||
export DEB_BUILD_MAINT_OPTIONS=hardening=+all
|
||||
|
||||
# get the various DEB_BUILD/DEB_HOST variables
|
||||
include /usr/share/dpkg/architecture.mk
|
||||
|
||||
override_dh_install:
|
||||
dh_install --autodest
|
||||
|
||||
%:
|
||||
dh $@
|
||||
81
plugins/httpd.c
Normal file
81
plugins/httpd.c
Normal file
@@ -0,0 +1,81 @@
|
||||
#include <pthread.h>
|
||||
|
||||
#include "../debug.h"
|
||||
#include "../mongoose.h"
|
||||
#include "httpd.h"
|
||||
|
||||
static const char *s_root_dir = ".";
|
||||
static const char *s_listening_address = "http://0.0.0.0:8000";
|
||||
|
||||
static void
|
||||
httpd_handler(struct mg_connection *c, int ev, void *ev_data, void *fn_data)
|
||||
{
|
||||
if (ev == MG_EV_HTTP_MSG)
|
||||
{
|
||||
struct mg_http_message *hm = ev_data, tmp = {0};
|
||||
struct mg_str unknown = mg_str_n("?", 1), *cl;
|
||||
struct mg_http_serve_opts opts = {0};
|
||||
opts.root_dir = s_root_dir;
|
||||
mg_http_serve_dir(c, hm, &opts);
|
||||
mg_http_parse((char *)c->send.buf, c->send.len, &tmp);
|
||||
cl = mg_http_get_header(&tmp, "Content-Length");
|
||||
if (cl == NULL)
|
||||
cl = &unknown;
|
||||
debug(LOG_INFO, "HTTP: %.*s %.*s %.*s %.*s\n",
|
||||
(int)hm->method.len, hm->method.ptr,
|
||||
(int)hm->uri.len, hm->uri.ptr,
|
||||
(int)tmp.uri.len, tmp.uri.ptr,
|
||||
(int)cl->len, cl->ptr);
|
||||
}
|
||||
(void)fn_data;
|
||||
}
|
||||
|
||||
static void *
|
||||
httpd_thread(void *arg)
|
||||
{
|
||||
char path[MG_PATH_MAX] = ".";
|
||||
struct mg_mgr mgr;
|
||||
struct mg_connection *c;
|
||||
struct proxy_service *ps = (struct proxy_service *)arg;
|
||||
|
||||
mg_mgr_init(&mgr);
|
||||
if ((c = mg_http_listen(&mgr, s_listening_address, httpd_handler, &mgr)) == NULL)
|
||||
{
|
||||
debug(LOG_ERR, "Cannot listen on %s. Use http://ADDR:PORT or :PORT",
|
||||
s_listening_address);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Root directory must not contain double dots. Make it absolute
|
||||
// Do the conversion only if the root dir spec does not contain overrides
|
||||
if (strchr(ps->s_root_dir, ',') == NULL)
|
||||
{
|
||||
realpath(ps->s_root_dir, path);
|
||||
s_root_dir = path;
|
||||
}
|
||||
|
||||
debug(LOG_INFO, "Listening on : %s", s_listening_address);
|
||||
debug(LOG_INFO, "Web root : [%s]", s_root_dir);
|
||||
while (1)
|
||||
mg_mgr_poll(&mgr, 1000);
|
||||
mg_mgr_free(&mgr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void start_httpd_service(struct proxy_service *ps)
|
||||
{
|
||||
// start a httpd service in a new thread
|
||||
pthread_t thread;
|
||||
|
||||
if (pthread_create(&thread, NULL, httpd_thread, ps) != 0)
|
||||
{
|
||||
debug(LOG_ERR, "Failed to create thread\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
//detach thread
|
||||
pthread_detach(thread);
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
8
plugins/httpd.h
Normal file
8
plugins/httpd.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef _HTTPD_H
|
||||
#define _HTTPD_H
|
||||
|
||||
#include "../client.h"
|
||||
|
||||
void start_httpd_service(struct proxy_service *ps);
|
||||
|
||||
#endif
|
||||
247
plugins/instaloader.c
Normal file
247
plugins/instaloader.c
Normal file
@@ -0,0 +1,247 @@
|
||||
#include <json-c/json.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <event2/http.h>
|
||||
|
||||
#include "../common.h"
|
||||
#include "../debug.h"
|
||||
#include "../config.h"
|
||||
#include "instaloader.h"
|
||||
|
||||
struct instaloader_param {
|
||||
char action[10];
|
||||
char profile[100];
|
||||
};
|
||||
|
||||
// define instaloader worker function
|
||||
static void *
|
||||
instaloader_worker(void *param)
|
||||
{
|
||||
struct instaloader_param *p = (struct instaloader_param *)param;
|
||||
debug(LOG_DEBUG, "instaloader: action: %s, profile: %s\n", p->action, p->profile);
|
||||
char cmd[512] = {0};
|
||||
|
||||
// create directory instaloader and change current directory to it
|
||||
snprintf(cmd, sizeof(cmd), "mkdir -p instaloader && cd instaloader");
|
||||
debug(LOG_DEBUG, "instaloader: cmd: %s\n", cmd);
|
||||
system(cmd);
|
||||
|
||||
if (strcmp(p->action, "download") == 0) {
|
||||
// download profile
|
||||
snprintf(cmd, sizeof(cmd), "instaloader --no-captions --no-metadata-json --no-compress-json --no-pictures %s", p->profile);
|
||||
debug(LOG_DEBUG, "instaloader: cmd: %s\n", cmd);
|
||||
// use popen to execute cmd and get its output
|
||||
FILE *fp = popen(cmd, "r");
|
||||
if (fp == NULL) {
|
||||
debug(LOG_ERR, "instaloader: popen failed\n");
|
||||
free(param);
|
||||
return NULL;
|
||||
}
|
||||
char buf[512] = {0};
|
||||
while (fgets(buf, sizeof(buf), fp) != NULL) {
|
||||
debug(LOG_DEBUG, "instaloader: %s", buf);
|
||||
memset(buf, 0, sizeof(buf));
|
||||
}
|
||||
pclose(fp);
|
||||
} else if (strcmp(p->action, "stop") == 0) {
|
||||
// stop instaloader
|
||||
debug(LOG_DEBUG, "instaloader: exit the program \n");
|
||||
exit(0);
|
||||
} else {
|
||||
debug(LOG_ERR, "instaloader: unknown action: %s\n", p->action);
|
||||
}
|
||||
|
||||
// free param
|
||||
free(param);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_instaloader_command(char *json_data, struct instaloader_param *param)
|
||||
{
|
||||
// parse json data with json-c to param
|
||||
json_object *jobj = json_tokener_parse(json_data);
|
||||
if (jobj == NULL) {
|
||||
debug(LOG_ERR, "instaloader: json_tokener_parse failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// get action
|
||||
json_object *jaction = NULL;
|
||||
if (!json_object_object_get_ex(jobj, "action", &jaction)) {
|
||||
debug(LOG_ERR, "instaloader: json_object_object_get_ex failed\n");
|
||||
json_object_put(jobj);
|
||||
return -1;
|
||||
}
|
||||
strcpy(param->action, json_object_get_string(jaction));
|
||||
if (strcmp(param->action, "stop") == 0) {
|
||||
json_object_put(jobj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get profile
|
||||
json_object *jprofile = NULL;
|
||||
if (!json_object_object_get_ex(jobj, "profile", &jprofile)) {
|
||||
debug(LOG_ERR, "instaloader: json_object_object_get_ex failed\n");
|
||||
json_object_put(jobj);
|
||||
return -1;
|
||||
}
|
||||
strcpy(param->profile, json_object_get_string(jprofile));
|
||||
|
||||
// free json object
|
||||
json_object_put(jobj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
instaloader_response(struct evhttp_request *req, char *result)
|
||||
{
|
||||
struct evbuffer *resp = evbuffer_new();
|
||||
evbuffer_add_printf(resp, "{\"status\": \"%s\"}", result);
|
||||
evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "application/json");
|
||||
evhttp_send_reply(req, HTTP_OK, "OK", resp);
|
||||
}
|
||||
|
||||
// define instaloader read callback function
|
||||
static void
|
||||
instaloader_read_cb(struct evhttp_request *req, void *args)
|
||||
{
|
||||
#define BUFF_LEN 4096
|
||||
// read data from bufferevent
|
||||
char data[BUFF_LEN] = {0};
|
||||
struct evbuffer *input = evhttp_request_get_input_buffer(req);
|
||||
size_t len = evbuffer_get_length(input);
|
||||
assert(len < BUFF_LEN);
|
||||
if (len >= BUFF_LEN) {
|
||||
debug(LOG_ERR, "instaloader: data length is too long\n");
|
||||
instaloader_response(req, "data length is too long");
|
||||
return;
|
||||
}
|
||||
debug(LOG_DEBUG, "instaloader: data: %s\n", data);
|
||||
|
||||
// parse http post and get its json data
|
||||
evbuffer_copyout(input, data, len);
|
||||
debug(LOG_DEBUG, "instaloader: data: %s\n", data);
|
||||
|
||||
struct instaloader_param *param = (struct instaloader_param *)malloc(sizeof(struct instaloader_param));
|
||||
assert(param != NULL);
|
||||
memset(param, 0, sizeof(struct instaloader_param));
|
||||
|
||||
int nret = parse_instaloader_command(data, param);
|
||||
if (nret != 0) {
|
||||
debug(LOG_ERR, "instaloader: parse_command failed\n");
|
||||
free(param);
|
||||
instaloader_response(req, "failed to parse command");
|
||||
return;
|
||||
}
|
||||
|
||||
// create a thread
|
||||
pthread_t thread;
|
||||
// create a thread attribute
|
||||
pthread_attr_t attr;
|
||||
// initialize thread attribute
|
||||
pthread_attr_init(&attr);
|
||||
// set thread attribute to detach
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
// create a thread
|
||||
pthread_create(&thread, &attr, instaloader_worker, param);
|
||||
// destroy thread attribute
|
||||
pthread_attr_destroy(&attr);
|
||||
|
||||
instaloader_response(req, "ok");
|
||||
}
|
||||
|
||||
// define instaloader http post callback function
|
||||
static void
|
||||
http_post_cb(struct evhttp_request *req, void *arg)
|
||||
{
|
||||
// check http request method
|
||||
if (evhttp_request_get_command(req) != EVHTTP_REQ_POST) {
|
||||
debug(LOG_ERR, "instaloader: http request method is not POST\n");
|
||||
evhttp_send_error(req, HTTP_BADMETHOD, "Method Not Allowed");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the HTTP request content type
|
||||
const char *content_type = evhttp_find_header(evhttp_request_get_input_headers(req), "Content-Type");
|
||||
if (content_type == NULL || strcmp(content_type, "application/json") != 0) {
|
||||
debug(LOG_ERR, "instaloader: http request content type is not application/json\n");
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
return;
|
||||
}
|
||||
|
||||
// get json data from http request
|
||||
instaloader_read_cb(req, arg);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// define instaloader service
|
||||
static void *
|
||||
instaloader_service(void *local_port)
|
||||
{
|
||||
uint16_t port = *(uint16_t *)local_port;
|
||||
free(local_port);
|
||||
// Initialize libevent
|
||||
struct event_base *base = event_base_new();
|
||||
if (!base) {
|
||||
debug(LOG_ERR, "instaloader: Failed to initialize libevent\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create a new HTTP server
|
||||
struct evhttp *http = evhttp_new(base);
|
||||
if (!http) {
|
||||
debug(LOG_ERR, "Failed to create HTTP server\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
if (evhttp_bind_socket(http, "0.0.0.0", port) != 0) {
|
||||
debug(LOG_ERR, "Failed to bind HTTP server to port %d\n", port);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
debug(LOG_DEBUG, "instaloader: start instaloader service on port %d\n", port);
|
||||
|
||||
// Set up a callback function for handling HTTP requests
|
||||
evhttp_set_cb(http, "/", http_post_cb, NULL);
|
||||
|
||||
// Start the event loop
|
||||
event_base_dispatch(base);
|
||||
|
||||
// Clean up
|
||||
evhttp_free(http);
|
||||
event_base_free(base);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
start_instaloader_service(uint16_t local_port)
|
||||
{
|
||||
uint16_t *p = (uint16_t *)malloc(sizeof(uint16_t));
|
||||
assert(p != NULL);
|
||||
*p = local_port;
|
||||
// create a thread
|
||||
pthread_t thread;
|
||||
// create a thread attribute
|
||||
pthread_attr_t attr;
|
||||
// initialize thread attribute
|
||||
pthread_attr_init(&attr);
|
||||
// set thread attribute to detach
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
// create a thread
|
||||
pthread_create(&thread, &attr, instaloader_service, (void *)p);
|
||||
// destroy thread attribute
|
||||
pthread_attr_destroy(&attr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
6
plugins/instaloader.h
Normal file
6
plugins/instaloader.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef _INSTALOADER_H_
|
||||
#define _INSTALOADER_H_
|
||||
|
||||
int start_instaloader_service(uint16_t local_port);
|
||||
|
||||
#endif
|
||||
615
plugins/telnetd.c
Normal file
615
plugins/telnetd.c
Normal file
@@ -0,0 +1,615 @@
|
||||
/*
|
||||
* Simple telnet server
|
||||
* Bjorn Wesen, Axis Communications AB (bjornw@axis.com)
|
||||
*
|
||||
* This file is distributed under the GNU Public License (GPL),
|
||||
* please see the file LICENSE for further information.
|
||||
*
|
||||
* ---------------------------------------------------------------------------
|
||||
* (C) Copyright 2000, Axis Communications AB, LUND, SWEDEN
|
||||
****************************************************************************
|
||||
*
|
||||
* The telnetd manpage says it all:
|
||||
*
|
||||
* Telnetd operates by allocating a pseudo-terminal device (see pty(4)) for
|
||||
* a client, then creating a login process which has the slave side of the
|
||||
* pseudo-terminal as stdin, stdout, and stderr. Telnetd manipulates the
|
||||
* master side of the pseudo-terminal, implementing the telnet protocol and
|
||||
* passing characters between the remote client and the login process.
|
||||
*
|
||||
* Vladimir Oleynik <dzo@simtreas.ru> 2001
|
||||
* Set process group corrections, initial busybox port
|
||||
*
|
||||
* BusyBox is distributed under version 2 of the General Public License please
|
||||
* see the file LICENSE for further information. Version 2 is the only version
|
||||
* of this license which this version of BusyBox
|
||||
* (or modified versions derived from this one) may be
|
||||
* distributed under.
|
||||
* https://busybox.net/downloads/busybox-0.60.5.tar.bz2
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <netinet/in.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <arpa/telnet.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "telnetd.h"
|
||||
#include "../debug.h"
|
||||
|
||||
|
||||
typedef struct sockaddr_in sockaddr_type;
|
||||
static const char *loginpath = "/bin/login";
|
||||
|
||||
/* shell name and arguments */
|
||||
|
||||
static const char *argv_init[] = {NULL, NULL};
|
||||
|
||||
/* structure that describes a session */
|
||||
|
||||
struct tsession
|
||||
{
|
||||
struct tsession *next;
|
||||
int sockfd, ptyfd;
|
||||
int shell_pid;
|
||||
/* two circular buffers */
|
||||
char *buf1, *buf2;
|
||||
int rdidx1, wridx1, size1;
|
||||
int rdidx2, wridx2, size2;
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
This is how the buffers are used. The arrows indicate the movement
|
||||
of data.
|
||||
|
||||
+-------+ wridx1++ +------+ rdidx1++ +----------+
|
||||
| | <-------------- | buf1 | <-------------- | |
|
||||
| | size1-- +------+ size1++ | |
|
||||
| pty | | socket |
|
||||
| | rdidx2++ +------+ wridx2++ | |
|
||||
| | --------------> | buf2 | --------------> | |
|
||||
+-------+ size2++ +------+ size2-- +----------+
|
||||
|
||||
Each session has got two buffers.
|
||||
|
||||
*/
|
||||
|
||||
static int maxfd;
|
||||
static struct tsession *sessions;
|
||||
|
||||
/*
|
||||
|
||||
Remove all IAC's from the buffer pointed to by bf (recieved IACs are ignored
|
||||
and must be removed so as to not be interpreted by the terminal). Make an
|
||||
uninterrupted string of characters fit for the terminal. Do this by packing
|
||||
all characters meant for the terminal sequentially towards the end of bf.
|
||||
|
||||
Return a pointer to the beginning of the characters meant for the terminal.
|
||||
and make *num_totty the number of characters that should be sent to
|
||||
the terminal.
|
||||
|
||||
Note - If an IAC (3 byte quantity) starts before (bf + len) but extends
|
||||
past (bf + len) then that IAC will be left unprocessed and *processed will be
|
||||
less than len.
|
||||
|
||||
FIXME - if we mean to send 0xFF to the terminal then it will be escaped,
|
||||
what is the escape character? We aren't handling that situation here.
|
||||
|
||||
CR-LF ->'s CR mapping is also done here, for convenience
|
||||
|
||||
*/
|
||||
static char *
|
||||
remove_iacs(struct tsession *ts, int *pnum_totty)
|
||||
{
|
||||
unsigned char *ptr0 = ts->buf1 + ts->wridx1;
|
||||
unsigned char *ptr = ptr0;
|
||||
unsigned char *totty = ptr;
|
||||
unsigned char *end = ptr + MIN(BUFSIZE - ts->wridx1, ts->size1);
|
||||
int processed;
|
||||
int num_totty;
|
||||
|
||||
while (ptr < end)
|
||||
{
|
||||
if (*ptr != IAC)
|
||||
{
|
||||
int c = *ptr;
|
||||
*totty++ = *ptr++;
|
||||
/* We now map \r\n ==> \r for pragmatic reasons.
|
||||
* Many client implementations send \r\n when
|
||||
* the user hits the CarriageReturn key.
|
||||
*/
|
||||
if (c == '\r' && (*ptr == '\n' || *ptr == 0) && ptr < end)
|
||||
ptr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* TELOPT_NAWS support!
|
||||
*/
|
||||
if ((ptr + 2) >= end)
|
||||
{
|
||||
/* only the beginning of the IAC is in the
|
||||
buffer we were asked to process, we can't
|
||||
process this char. */
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* IAC -> SB -> TELOPT_NAWS -> 4-byte -> IAC -> SE
|
||||
*/
|
||||
else if (ptr[1] == SB && ptr[2] == TELOPT_NAWS)
|
||||
{
|
||||
struct winsize ws;
|
||||
if ((ptr + 8) >= end)
|
||||
break; /* incomplete, can't process */
|
||||
ws.ws_col = (ptr[3] << 8) | ptr[4];
|
||||
ws.ws_row = (ptr[5] << 8) | ptr[6];
|
||||
(void)ioctl(ts->ptyfd, TIOCSWINSZ, (char *)&ws);
|
||||
ptr += 9;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* skip 3-byte IAC non-SB cmd */
|
||||
ptr += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processed = ptr - ptr0;
|
||||
num_totty = totty - ptr0;
|
||||
/* the difference between processed and num_to tty
|
||||
is all the iacs we removed from the stream.
|
||||
Adjust buf1 accordingly. */
|
||||
ts->wridx1 += processed - num_totty;
|
||||
ts->size1 -= processed - num_totty;
|
||||
*pnum_totty = num_totty;
|
||||
/* move the chars meant for the terminal towards the end of the
|
||||
buffer. */
|
||||
return memmove(ptr - num_totty, ptr0, num_totty);
|
||||
}
|
||||
|
||||
static int
|
||||
getpty(char *line)
|
||||
{
|
||||
#ifdef OLD_GETPTY
|
||||
int p;
|
||||
p = open("/dev/ptmx", 2);
|
||||
if (p > 0)
|
||||
{
|
||||
grantpt(p);
|
||||
unlockpt(p);
|
||||
strcpy(line, ptsname(p));
|
||||
return (p);
|
||||
}
|
||||
return -1;
|
||||
#else
|
||||
|
||||
int p;
|
||||
p = open("/dev/ptmx", O_RDWR);
|
||||
if (p >= 0)
|
||||
{
|
||||
grantpt(p);
|
||||
unlockpt(p);
|
||||
if (ptsname_r(p, line, GETPTY_BUFSIZE - 1) != 0)
|
||||
{
|
||||
debug(LOG_ERR, "ptsname error (is /dev/pts mounted?)");
|
||||
return -1;
|
||||
}
|
||||
line[GETPTY_BUFSIZE - 1] = '\0';
|
||||
return p;
|
||||
}
|
||||
struct stat stb;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
strcpy(line, "/dev/ptyXX");
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
line[8] = "pqrstuvwxyzabcde"[i];
|
||||
line[9] = '0';
|
||||
if (stat(line, &stb) < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for (j = 0; j < 16; j++)
|
||||
{
|
||||
line[9] = j < 10 ? j + '0' : j - 10 + 'a';
|
||||
p = open(line, O_RDWR | O_NOCTTY);
|
||||
if (p >= 0)
|
||||
{
|
||||
line[5] = 't';
|
||||
return p;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
send_iac(struct tsession *ts, unsigned char command, int option)
|
||||
{
|
||||
/* We rely on that there is space in the buffer for now. */
|
||||
char *b = ts->buf2 + ts->rdidx2;
|
||||
*b++ = IAC;
|
||||
*b++ = command;
|
||||
*b++ = option;
|
||||
ts->rdidx2 += 3;
|
||||
ts->size2 += 3;
|
||||
}
|
||||
|
||||
static struct tsession *
|
||||
make_new_session(int sockfd)
|
||||
{
|
||||
struct termios termbuf;
|
||||
int pty, pid;
|
||||
char tty_name[32];
|
||||
struct tsession *ts = malloc(sizeof(struct tsession) + BUFSIZE * 2);
|
||||
|
||||
ts->buf1 = (char *)(&ts[1]);
|
||||
ts->buf2 = ts->buf1 + BUFSIZE;
|
||||
ts->sockfd = sockfd;
|
||||
|
||||
ts->rdidx1 = ts->wridx1 = ts->size1 = 0;
|
||||
ts->rdidx2 = ts->wridx2 = ts->size2 = 0;
|
||||
|
||||
/* Got a new connection, set up a tty and spawn a shell. */
|
||||
|
||||
pty = getpty(tty_name);
|
||||
|
||||
if (pty < 0)
|
||||
{
|
||||
debug(LOG_ERR, "All network ports in use!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pty > maxfd)
|
||||
maxfd = pty;
|
||||
|
||||
ts->ptyfd = pty;
|
||||
|
||||
/* Make the telnet client understand we will echo characters so it
|
||||
* should not do it locally. We don't tell the client to run linemode,
|
||||
* because we want to handle line editing and tab completion and other
|
||||
* stuff that requires char-by-char support.
|
||||
*/
|
||||
|
||||
send_iac(ts, DO, TELOPT_ECHO);
|
||||
send_iac(ts, DO, TELOPT_NAWS);
|
||||
send_iac(ts, DO, TELOPT_LFLOW);
|
||||
send_iac(ts, WILL, TELOPT_ECHO);
|
||||
send_iac(ts, WILL, TELOPT_SGA);
|
||||
|
||||
if ((pid = fork()) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "Can`t forking");
|
||||
}
|
||||
if (pid == 0)
|
||||
{
|
||||
/* In child, open the child's side of the tty. */
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= maxfd; i++)
|
||||
close(i);
|
||||
/* make new process group */
|
||||
setsid();
|
||||
|
||||
if (open(tty_name, O_RDWR) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "Could not open tty");
|
||||
exit(1);
|
||||
}
|
||||
dup(0);
|
||||
dup(0);
|
||||
|
||||
tcsetpgrp(0, getpid());
|
||||
|
||||
/* The pseudo-terminal allocated to the client is configured to operate in
|
||||
* cooked mode, and with XTABS CRMOD enabled (see tty(4)).
|
||||
*/
|
||||
|
||||
tcgetattr(0, &termbuf);
|
||||
termbuf.c_lflag |= ECHO; /* if we use readline we dont want this */
|
||||
termbuf.c_oflag |= ONLCR | XTABS;
|
||||
termbuf.c_iflag |= ICRNL;
|
||||
termbuf.c_iflag &= ~IXOFF;
|
||||
/*termbuf.c_lflag &= ~ICANON;*/
|
||||
tcsetattr(0, TCSANOW, &termbuf);
|
||||
|
||||
/* exec shell, with correct argv and env */
|
||||
execv(loginpath, (char *const *)argv_init);
|
||||
|
||||
/* NOT REACHED */
|
||||
syslog(LOG_ERR, "execv error");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ts->shell_pid = pid;
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
||||
static void
|
||||
free_session(struct tsession *ts)
|
||||
{
|
||||
struct tsession *t = sessions;
|
||||
|
||||
/* Unlink this telnet session from the session list. */
|
||||
if (t == ts)
|
||||
sessions = ts->next;
|
||||
else
|
||||
{
|
||||
while (t->next != ts)
|
||||
t = t->next;
|
||||
t->next = ts->next;
|
||||
}
|
||||
|
||||
kill(ts->shell_pid, SIGKILL);
|
||||
|
||||
wait4(ts->shell_pid, NULL, 0, NULL);
|
||||
|
||||
close(ts->ptyfd);
|
||||
close(ts->sockfd);
|
||||
|
||||
if (ts->ptyfd == maxfd || ts->sockfd == maxfd)
|
||||
maxfd--;
|
||||
if (ts->ptyfd == maxfd || ts->sockfd == maxfd)
|
||||
maxfd--;
|
||||
|
||||
free(ts);
|
||||
}
|
||||
|
||||
// create a function for a thread, so we can use it in the main function
|
||||
static void *
|
||||
simple_telnetd_thread(void *arg)
|
||||
{
|
||||
sockaddr_type sa;
|
||||
int master_fd;
|
||||
fd_set rdfdset, wrfdset;
|
||||
int selret;
|
||||
int on = 1;
|
||||
uint16_t portnbr = arg ? *(uint16_t *)arg : 2323;
|
||||
int maxlen, w, r;
|
||||
free(arg);
|
||||
debug(LOG_INFO, "Starting telnetd on port %d\n", portnbr);
|
||||
|
||||
if (access(loginpath, X_OK) < 0)
|
||||
{
|
||||
debug(LOG_ERR, "No login shell found at %s\n", loginpath);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
argv_init[0] = loginpath;
|
||||
sessions = 0;
|
||||
|
||||
/* Grab a TCP socket. */
|
||||
master_fd = socket(SOCKET_TYPE, SOCK_STREAM, 0);
|
||||
if (master_fd < 0)
|
||||
{
|
||||
debug(LOG_ERR, "Unable to create socket\n");
|
||||
return NULL;
|
||||
}
|
||||
(void)setsockopt(master_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
||||
|
||||
/* Set it to listen to specified port. */
|
||||
memset((void *)&sa, 0, sizeof(sa));
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = htons(portnbr);
|
||||
|
||||
if (bind(master_fd, (struct sockaddr *)&sa, sizeof(sa)) < 0)
|
||||
{
|
||||
debug(LOG_ERR, "Failed to bind socket: %s\n", strerror(errno));
|
||||
close(master_fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (listen(master_fd, 1) < 0)
|
||||
{
|
||||
debug(LOG_ERR, "Socket failed to listen\n");
|
||||
close(master_fd);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
maxfd = master_fd;
|
||||
|
||||
do
|
||||
{
|
||||
struct tsession *ts;
|
||||
|
||||
FD_ZERO(&rdfdset);
|
||||
FD_ZERO(&wrfdset);
|
||||
|
||||
/* select on the master socket, all telnet sockets and their
|
||||
* ptys if there is room in their respective session buffers.
|
||||
*/
|
||||
|
||||
FD_SET(master_fd, &rdfdset);
|
||||
|
||||
ts = sessions;
|
||||
while (ts)
|
||||
{
|
||||
/* buf1 is used from socket to pty
|
||||
* buf2 is used from pty to socket
|
||||
*/
|
||||
if (ts->size1 > 0)
|
||||
{
|
||||
FD_SET(ts->ptyfd, &wrfdset); /* can write to pty */
|
||||
}
|
||||
if (ts->size1 < BUFSIZE)
|
||||
{
|
||||
FD_SET(ts->sockfd, &rdfdset); /* can read from socket */
|
||||
}
|
||||
if (ts->size2 > 0)
|
||||
{
|
||||
FD_SET(ts->sockfd, &wrfdset); /* can write to socket */
|
||||
}
|
||||
if (ts->size2 < BUFSIZE)
|
||||
{
|
||||
FD_SET(ts->ptyfd, &rdfdset); /* can read from pty */
|
||||
}
|
||||
ts = ts->next;
|
||||
}
|
||||
|
||||
selret = select(maxfd + 1, &rdfdset, &wrfdset, 0, 0);
|
||||
|
||||
if (!selret)
|
||||
break;
|
||||
/* First check for and accept new sessions. */
|
||||
if (FD_ISSET(master_fd, &rdfdset))
|
||||
{
|
||||
int fd, salen;
|
||||
|
||||
salen = sizeof(sa);
|
||||
if ((fd = accept(master_fd, (struct sockaddr *)&sa,
|
||||
&salen)) < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Create a new session and link it into
|
||||
our active list. */
|
||||
struct tsession *new_ts = make_new_session(fd);
|
||||
if (new_ts)
|
||||
{
|
||||
new_ts->next = sessions;
|
||||
sessions = new_ts;
|
||||
if (fd > maxfd)
|
||||
maxfd = fd;
|
||||
}
|
||||
else
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Then check for data tunneling. */
|
||||
ts = sessions;
|
||||
while (ts)
|
||||
{ /* For all sessions... */
|
||||
struct tsession *next = ts->next; /* in case we free ts. */
|
||||
|
||||
if (ts->size1 && FD_ISSET(ts->ptyfd, &wrfdset))
|
||||
{
|
||||
int num_totty;
|
||||
char *ptr;
|
||||
/* Write to pty from buffer 1. */
|
||||
|
||||
ptr = remove_iacs(ts, &num_totty);
|
||||
|
||||
w = write(ts->ptyfd, ptr, num_totty);
|
||||
if (w < 0)
|
||||
{
|
||||
free_session(ts);
|
||||
ts = next;
|
||||
continue;
|
||||
}
|
||||
ts->wridx1 += w;
|
||||
ts->size1 -= w;
|
||||
if (ts->wridx1 == BUFSIZE)
|
||||
ts->wridx1 = 0;
|
||||
}
|
||||
|
||||
if (ts->size2 && FD_ISSET(ts->sockfd, &wrfdset))
|
||||
{
|
||||
/* Write to socket from buffer 2. */
|
||||
maxlen = MIN(BUFSIZE - ts->wridx2, ts->size2);
|
||||
w = write(ts->sockfd, ts->buf2 + ts->wridx2, maxlen);
|
||||
if (w < 0)
|
||||
{
|
||||
free_session(ts);
|
||||
ts = next;
|
||||
continue;
|
||||
}
|
||||
ts->wridx2 += w;
|
||||
ts->size2 -= w;
|
||||
if (ts->wridx2 == BUFSIZE)
|
||||
ts->wridx2 = 0;
|
||||
}
|
||||
|
||||
if (ts->size1 < BUFSIZE && FD_ISSET(ts->sockfd, &rdfdset))
|
||||
{
|
||||
/* Read from socket to buffer 1. */
|
||||
maxlen = MIN(BUFSIZE - ts->rdidx1,
|
||||
BUFSIZE - ts->size1);
|
||||
r = read(ts->sockfd, ts->buf1 + ts->rdidx1, maxlen);
|
||||
if (!r || (r < 0 && errno != EINTR))
|
||||
{
|
||||
free_session(ts);
|
||||
ts = next;
|
||||
continue;
|
||||
}
|
||||
if (!*(ts->buf1 + ts->rdidx1 + r - 1))
|
||||
{
|
||||
r--;
|
||||
if (!r)
|
||||
continue;
|
||||
}
|
||||
ts->rdidx1 += r;
|
||||
ts->size1 += r;
|
||||
if (ts->rdidx1 == BUFSIZE)
|
||||
ts->rdidx1 = 0;
|
||||
}
|
||||
|
||||
if (ts->size2 < BUFSIZE && FD_ISSET(ts->ptyfd, &rdfdset))
|
||||
{
|
||||
/* Read from pty to buffer 2. */
|
||||
maxlen = MIN(BUFSIZE - ts->rdidx2,
|
||||
BUFSIZE - ts->size2);
|
||||
r = read(ts->ptyfd, ts->buf2 + ts->rdidx2, maxlen);
|
||||
if (!r || (r < 0 && errno != EINTR))
|
||||
{
|
||||
free_session(ts);
|
||||
ts = next;
|
||||
continue;
|
||||
}
|
||||
ts->rdidx2 += r;
|
||||
ts->size2 += r;
|
||||
if (ts->rdidx2 == BUFSIZE)
|
||||
ts->rdidx2 = 0;
|
||||
}
|
||||
|
||||
if (ts->size1 == 0)
|
||||
{
|
||||
ts->rdidx1 = 0;
|
||||
ts->wridx1 = 0;
|
||||
}
|
||||
if (ts->size2 == 0)
|
||||
{
|
||||
ts->rdidx2 = 0;
|
||||
ts->wridx2 = 0;
|
||||
}
|
||||
ts = next;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
simple_telnetd_start(uint16_t port)
|
||||
{
|
||||
pthread_t thread;
|
||||
uint16_t *port_ptr = malloc(sizeof(uint16_t));
|
||||
*port_ptr = port;
|
||||
pthread_create(&thread, NULL, simple_telnetd_thread, port_ptr);
|
||||
return 0;
|
||||
}
|
||||
14
plugins/telnetd.h
Normal file
14
plugins/telnetd.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef _TELNETD_H
|
||||
#define _TELNETD_H
|
||||
|
||||
#define BUFSIZE 4000
|
||||
#define SOCKET_TYPE AF_INET
|
||||
#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
|
||||
enum
|
||||
{
|
||||
GETPTY_BUFSIZE = 16
|
||||
};
|
||||
|
||||
int simple_telnetd_start(uint16_t port);
|
||||
|
||||
#endif
|
||||
289
plugins/youtubedl.c
Normal file
289
plugins/youtubedl.c
Normal file
@@ -0,0 +1,289 @@
|
||||
|
||||
|
||||
#include <json-c/json.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <event2/http.h>
|
||||
|
||||
#include "../common.h"
|
||||
#include "../debug.h"
|
||||
#include "../config.h"
|
||||
#include "youtubedl.h"
|
||||
|
||||
struct yt_dlp_param {
|
||||
char action[10];
|
||||
char profile[100];
|
||||
};
|
||||
|
||||
// define yt-dlp worker function
|
||||
static void *
|
||||
yt_dlp_worker(void *param)
|
||||
{
|
||||
struct yt_dlp_param *p = (struct yt_dlp_param *)param;
|
||||
debug(LOG_DEBUG, "yt-dlp: action: %s, url: %s\n", p->action, p->profile);
|
||||
char cmd[512] = {0};
|
||||
|
||||
// create directory yt-dlp and change current directory to it
|
||||
snprintf(cmd, sizeof(cmd), "mkdir -p yt-dlp && cd yt-dlp");
|
||||
debug(LOG_DEBUG, "yt-dlp: cmd: %s\n", cmd);
|
||||
system(cmd);
|
||||
|
||||
if (strcmp(p->action, "download") == 0) {
|
||||
// download profile
|
||||
snprintf(cmd, sizeof(cmd), "yt-dlp %s", p->profile);
|
||||
debug(LOG_DEBUG, "yt-dlp: cmd: %s\n", cmd);
|
||||
// use popen to execute cmd and get its output
|
||||
FILE *fp = popen(cmd, "r");
|
||||
if (fp == NULL) {
|
||||
debug(LOG_ERR, "yt-dlp: popen failed\n");
|
||||
free(param);
|
||||
return NULL;
|
||||
}
|
||||
char buf[512] = {0};
|
||||
while (fgets(buf, sizeof(buf), fp) != NULL) {
|
||||
debug(LOG_DEBUG, "yt-dlp: %s", buf);
|
||||
memset(buf, 0, sizeof(buf));
|
||||
}
|
||||
pclose(fp);
|
||||
} else {
|
||||
debug(LOG_ERR, "yt-dlp: unknown action: %s\n", p->action);
|
||||
}
|
||||
|
||||
// free param
|
||||
free(param);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_yt_dlp_command(char *json_data, struct yt_dlp_param *param)
|
||||
{
|
||||
// parse json data with json-c to param
|
||||
json_object *jobj = json_tokener_parse(json_data);
|
||||
if (jobj == NULL) {
|
||||
debug(LOG_ERR, "yt-dlp: json_tokener_parse failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// get action
|
||||
json_object *jaction = NULL;
|
||||
if (!json_object_object_get_ex(jobj, "action", &jaction)) {
|
||||
debug(LOG_ERR, "yt-dlp: json_object_object_get_ex failed\n");
|
||||
json_object_put(jobj);
|
||||
return -1;
|
||||
}
|
||||
strcpy(param->action, json_object_get_string(jaction));
|
||||
if (strcmp(param->action, "stop") == 0) {
|
||||
json_object_put(jobj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get profile
|
||||
json_object *jprofile = NULL;
|
||||
if (!json_object_object_get_ex(jobj, "profile", &jprofile)) {
|
||||
debug(LOG_ERR, "yt-dlp: json_object_object_get_ex failed\n");
|
||||
json_object_put(jobj);
|
||||
return -1;
|
||||
}
|
||||
strcpy(param->profile, json_object_get_string(jprofile));
|
||||
|
||||
// free json object
|
||||
json_object_put(jobj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
yt_dlp_response(struct evhttp_request *req, char *result)
|
||||
{
|
||||
struct evbuffer *resp = evbuffer_new();
|
||||
evbuffer_add_printf(resp, "{\"status\": \"%s\"}", result);
|
||||
evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "application/json");
|
||||
evhttp_send_reply(req, HTTP_OK, "OK", resp);
|
||||
}
|
||||
|
||||
// define yt-dlp read callback function
|
||||
static void
|
||||
yt_dlp_read_cb(struct evhttp_request *req, void *args)
|
||||
{
|
||||
#define BUFF_LEN 4096
|
||||
// read data from bufferevent
|
||||
char data[BUFF_LEN] = {0};
|
||||
struct evbuffer *input = evhttp_request_get_input_buffer(req);
|
||||
size_t len = evbuffer_get_length(input);
|
||||
assert(len < BUFF_LEN);
|
||||
if (len >= BUFF_LEN) {
|
||||
debug(LOG_ERR, "yt-dlp: data length is too long\n");
|
||||
yt_dlp_response(req, "data length is too long");
|
||||
return;
|
||||
}
|
||||
debug(LOG_DEBUG, "yt-dlp: data: %s\n", data);
|
||||
|
||||
// parse http post and get its json data
|
||||
evbuffer_copyout(input, data, len);
|
||||
debug(LOG_DEBUG, "yt-dlp: data: %s\n", data);
|
||||
|
||||
struct yt_dlp_param *param = (struct yt_dlp_param *)malloc(sizeof(struct yt_dlp_param));
|
||||
assert(param != NULL);
|
||||
memset(param, 0, sizeof(struct yt_dlp_param));
|
||||
|
||||
int nret = parse_yt_dlp_command (data, param);
|
||||
if (nret != 0) {
|
||||
debug(LOG_ERR, "yt-dlp: parse_command failed\n");
|
||||
free(param);
|
||||
yt_dlp_response(req, "failed to parse command");
|
||||
return;
|
||||
}
|
||||
|
||||
// create a thread
|
||||
pthread_t thread;
|
||||
// create a thread attribute
|
||||
pthread_attr_t attr;
|
||||
// initialize thread attribute
|
||||
pthread_attr_init(&attr);
|
||||
// set thread attribute to detach
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
// create a thread
|
||||
pthread_create(&thread, &attr, yt_dlp_worker, param);
|
||||
// destroy thread attribute
|
||||
pthread_attr_destroy(&attr);
|
||||
|
||||
yt_dlp_response(req, "ok");
|
||||
}
|
||||
|
||||
// define yt-dlp http post callback function
|
||||
static void
|
||||
http_post_cb(struct evhttp_request *req, void *arg)
|
||||
{
|
||||
// check http request method
|
||||
if (evhttp_request_get_command(req) != EVHTTP_REQ_POST) {
|
||||
debug(LOG_ERR, "yt-dlp: http request method is not POST\n");
|
||||
evhttp_send_error(req, HTTP_BADMETHOD, "Method Not Allowed");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the HTTP request content type
|
||||
const char *content_type = evhttp_find_header(evhttp_request_get_input_headers(req), "Content-Type");
|
||||
if (content_type == NULL || strcmp(content_type, "application/json") != 0) {
|
||||
debug(LOG_ERR, "yt-dlp: http request content type is not application/json\n");
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
return;
|
||||
}
|
||||
|
||||
// get json data from http request
|
||||
yt_dlp_read_cb(req, arg);
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
install_yt_dlp()
|
||||
{
|
||||
// if yt-dlp exists, return
|
||||
if (access("/usr/local/bin/yt-dlp", F_OK) == 0) {
|
||||
debug(LOG_DEBUG, "yt-dlp: yt-dlp exists\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// install yt-dlp to /usr/local/bin
|
||||
// download yt-dlp through curl or wget if any of them exists
|
||||
char cmd[512] = {0};
|
||||
if (access("/usr/bin/curl", F_OK) == 0) {
|
||||
snprintf(cmd, sizeof(cmd), "sudo curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -o /usr/local/bin/yt-dlp");
|
||||
} else if (access("/usr/bin/wget", F_OK) == 0) {
|
||||
snprintf(cmd, sizeof(cmd), "sudo wget https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -O /usr/local/bin/yt-dlp");
|
||||
} else {
|
||||
debug(LOG_ERR, "yt-dlp: curl and wget are not installed\n");
|
||||
return -1;
|
||||
}
|
||||
debug(LOG_DEBUG, "yt-dlp: cmd: %s\n", cmd);
|
||||
int nret = system(cmd);
|
||||
if (nret != 0) {
|
||||
debug(LOG_ERR, "yt-dlp: system failed\n");
|
||||
return -1;
|
||||
}
|
||||
// change yt-dlp to executable
|
||||
snprintf(cmd, sizeof(cmd), "sudo chmod a+rx /usr/local/bin/yt-dlp");
|
||||
debug(LOG_DEBUG, "yt-dlp: cmd: %s\n", cmd);
|
||||
nret = system(cmd);
|
||||
if (nret != 0) {
|
||||
debug(LOG_ERR, "yt-dlp: system failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// define yt-dlp service
|
||||
static void *
|
||||
yt_dlp_service(void *local_port)
|
||||
{
|
||||
// install yt-dlp
|
||||
int nret = install_yt_dlp();
|
||||
if (nret != 0) {
|
||||
debug(LOG_ERR, "yt-dlp: install_yt_dlp failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint16_t port = *(uint16_t *)local_port;
|
||||
free(local_port);
|
||||
// Initialize libevent
|
||||
struct event_base *base = event_base_new();
|
||||
if (!base) {
|
||||
debug(LOG_ERR, "yt-dlp: Failed to initialize libevent\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create a new HTTP server
|
||||
struct evhttp *http = evhttp_new(base);
|
||||
if (!http) {
|
||||
debug(LOG_ERR, "yt-dlp: Failed to create HTTP server\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
if (evhttp_bind_socket(http, "0.0.0.0", port) != 0) {
|
||||
debug(LOG_ERR, "yt-dlp: Failed to bind HTTP server to port %d\n", port);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
debug(LOG_DEBUG, "yt-dlp: start youtube download service on port %d\n", port);
|
||||
|
||||
// Set up a callback function for handling HTTP requests
|
||||
evhttp_set_cb(http, "/", http_post_cb, NULL);
|
||||
|
||||
// Start the event loop
|
||||
event_base_dispatch(base);
|
||||
|
||||
// Clean up
|
||||
evhttp_free(http);
|
||||
event_base_free(base);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
start_youtubedl_service(uint16_t local_port)
|
||||
{
|
||||
uint16_t *p = (uint16_t *)malloc(sizeof(uint16_t));
|
||||
assert(p != NULL);
|
||||
*p = local_port;
|
||||
// create a thread
|
||||
pthread_t thread;
|
||||
// create a thread attribute
|
||||
pthread_attr_t attr;
|
||||
// initialize thread attribute
|
||||
pthread_attr_init(&attr);
|
||||
// set thread attribute to detach
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
// create a thread
|
||||
pthread_create(&thread, &attr, yt_dlp_service, (void *)p);
|
||||
// destroy thread attribute
|
||||
pthread_attr_destroy(&attr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
6
plugins/youtubedl.h
Normal file
6
plugins/youtubedl.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef _YOUTUBE_DL_H_
|
||||
#define _YOUTUBE_DL_H_
|
||||
|
||||
int start_youtubedl_service(uint16_t local_port);
|
||||
|
||||
#endif
|
||||
@@ -19,37 +19,42 @@
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
/** @file xfrp_client.c
|
||||
@brief xfrp client
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liudengfeng@kunteng.org>
|
||||
/** @file proxy.c
|
||||
@brief xfrp proxy implemented
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <event2/event.h>
|
||||
|
||||
#include "commandline.h"
|
||||
#include "client.h"
|
||||
#include "config.h"
|
||||
#include "uthash.h"
|
||||
#include "control.h"
|
||||
#include "debug.h"
|
||||
#include "xfrp_client.h"
|
||||
#include "crypto.h"
|
||||
#include "msg.h"
|
||||
#include "utils.h"
|
||||
#include "uthash.h"
|
||||
#include "common.h"
|
||||
#include "proxy.h"
|
||||
#include "config.h"
|
||||
|
||||
void xfrp_client_loop()
|
||||
struct proxy *
|
||||
new_proxy_obj(struct bufferevent *bev)
|
||||
{
|
||||
init_main_control();
|
||||
run_control();
|
||||
|
||||
close_main_control();
|
||||
struct proxy *p = (struct proxy *)calloc(1, sizeof(struct proxy));
|
||||
assert(p);
|
||||
p->bev = bev;
|
||||
p->remote_data_port = -1;
|
||||
p->proxy_name = NULL;
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
free_proxy_obj(struct proxy *p)
|
||||
{
|
||||
SAFE_FREE(p->proxy_name);
|
||||
SAFE_FREE(p);
|
||||
}
|
||||
74
proxy.h
Normal file
74
proxy.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* vim: set et ts=4 sts=4 sw=4 : */
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, contact: *
|
||||
* *
|
||||
* Free Software Foundation Voice: +1-617-542-5942 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
/** @file proxy.h
|
||||
@brief xfrp proxy header file
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
#ifndef _PROXY_H_
|
||||
#define _PROXY_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <event2/bufferevent.h>
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/listener.h>
|
||||
#include <event2/util.h>
|
||||
#include <event2/event.h>
|
||||
|
||||
#include "client.h"
|
||||
#include "common.h"
|
||||
#include "tcpmux.h"
|
||||
#include "msg.h"
|
||||
|
||||
#define IP_LEN 16
|
||||
|
||||
struct ftp_pasv {
|
||||
int code;
|
||||
char ftp_server_ip[IP_LEN];
|
||||
int ftp_server_port;
|
||||
};
|
||||
|
||||
struct proxy {
|
||||
struct bufferevent *bev;
|
||||
char *proxy_name;
|
||||
int remote_data_port; //used in ftp proxy
|
||||
};
|
||||
|
||||
void tcp_proxy_c2s_cb(struct bufferevent *bev, void *ctx);
|
||||
void tcp_proxy_s2c_cb(struct bufferevent *bev, void *ctx);
|
||||
void ftp_proxy_c2s_cb(struct bufferevent *bev, void *ctx);
|
||||
void ftp_proxy_s2c_cb(struct bufferevent *bev, void *ctx);
|
||||
void udp_proxy_c2s_cb(struct bufferevent *bev, void *ctx);
|
||||
void udp_proxy_s2c_cb(struct bufferevent *bev, void *ctx);
|
||||
|
||||
struct proxy *new_proxy_obj(struct bufferevent *bev);
|
||||
void free_proxy_obj(struct proxy *p);
|
||||
void set_ftp_data_proxy_tunnel(const char *ftp_proxy_name,
|
||||
struct ftp_pasv *local_fp,
|
||||
struct ftp_pasv *remote_fp);
|
||||
|
||||
uint32_t handle_socks5(struct proxy_client *client, struct ring_buffer *rb, int len);
|
||||
uint32_t handle_ss5(struct proxy_client *client, struct ring_buffer *rb, int len);
|
||||
|
||||
void handle_udp_packet(struct udp_packet *udp_pkt, struct proxy_client *client);
|
||||
|
||||
#endif //_PROXY_H_
|
||||
267
proxy_ftp.c
Normal file
267
proxy_ftp.c
Normal file
@@ -0,0 +1,267 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <event2/bufferevent.h>
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/listener.h>
|
||||
#include <event2/event.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "uthash.h"
|
||||
#include "common.h"
|
||||
#include "proxy.h"
|
||||
#include "config.h"
|
||||
#include "client.h"
|
||||
|
||||
#define FTP_PRO_BUF 256
|
||||
#define FTP_PASV_PORT_BLOCK 256
|
||||
|
||||
static struct ftp_pasv *new_ftp_pasv();
|
||||
static void free_ftp_pasv(struct ftp_pasv *fp);
|
||||
static struct ftp_pasv * pasv_unpack(char *data);
|
||||
static size_t pasv_pack(struct ftp_pasv *fp, char **pack_p);
|
||||
|
||||
void set_ftp_data_proxy_tunnel(const char *ftp_proxy_name,
|
||||
struct ftp_pasv *local_fp,
|
||||
struct ftp_pasv *remote_fp)
|
||||
{
|
||||
struct proxy_service *ps = NULL;
|
||||
char *ftp_data_proxy_name = get_ftp_data_proxy_name(ftp_proxy_name);
|
||||
|
||||
struct proxy_service *p_services = get_all_proxy_services();
|
||||
HASH_FIND_STR(p_services, ftp_data_proxy_name, ps);
|
||||
if (!ps) {
|
||||
debug(LOG_ERR,
|
||||
"error: ftp data proxy not inserted in proxy-service queue, it should not happend!");
|
||||
goto FTP_DATA_PROXY_TUNNEL_END;
|
||||
}
|
||||
|
||||
ps->local_port = local_fp->ftp_server_port;
|
||||
ps->local_ip = strdup(local_fp->ftp_server_ip);
|
||||
assert(ps->local_ip);
|
||||
|
||||
ps->remote_port = remote_fp->ftp_server_port;
|
||||
|
||||
debug(LOG_DEBUG,
|
||||
"set ftp proxy DATA port [local:remote] = [%d:%d]",
|
||||
ps->local_port, ps->remote_port);
|
||||
|
||||
FTP_DATA_PROXY_TUNNEL_END:
|
||||
free(ftp_data_proxy_name);
|
||||
}
|
||||
|
||||
// read from client-working host port
|
||||
void ftp_proxy_c2s_cb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
struct proxy *p = (struct proxy *)ctx;
|
||||
assert(p);
|
||||
struct bufferevent *partner = p->bev;
|
||||
|
||||
struct evbuffer *src, *dst;
|
||||
size_t len;
|
||||
src = bufferevent_get_input(bev);
|
||||
len = evbuffer_get_length(src);
|
||||
if (len < 0)
|
||||
return;
|
||||
|
||||
dst = bufferevent_get_output(partner);
|
||||
assert(dst);
|
||||
|
||||
unsigned char *buf = calloc(1, len);
|
||||
assert(buf);
|
||||
size_t read_n = 0;
|
||||
read_n = evbuffer_remove(src, buf, len);
|
||||
|
||||
// #define FTP_P_DEBUG 1
|
||||
#ifdef FTP_P_DEBUG
|
||||
char *dbg_buf = calloc(1, read_n * 7 + 1);
|
||||
assert(dbg_buf);
|
||||
unsigned int i = 0;
|
||||
for(i = 0; i<read_n && ((2 * i) < (read_n * 2 + 1)); i++) {
|
||||
snprintf(dbg_buf + 7*i, 8, "%3u[%c] ",
|
||||
(unsigned char)buf[i],
|
||||
(unsigned char)buf[i]);
|
||||
}
|
||||
debug(LOG_DEBUG, "FTP Client RECV ctl byte:%s", dbg_buf);
|
||||
debug(LOG_DEBUG, "FTP Client RECV ctl stri:%s", buf);
|
||||
SAFE_FREE(dbg_buf);
|
||||
#endif //FTP_P_DEBUG
|
||||
|
||||
struct ftp_pasv *local_fp = pasv_unpack((char *)buf);
|
||||
|
||||
if (local_fp) {
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
struct ftp_pasv *r_fp = new_ftp_pasv();
|
||||
r_fp->code = local_fp->code;
|
||||
|
||||
if (! c_conf->server_addr) {
|
||||
debug(LOG_ERR, "error: FTP proxy without server ip!");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
strncpy(r_fp->ftp_server_ip, c_conf->server_addr, IP_LEN);
|
||||
r_fp->ftp_server_port = p->remote_data_port;
|
||||
|
||||
if (r_fp->ftp_server_port <= 0) {
|
||||
debug(LOG_ERR, "error: remote ftp data port is not init!");
|
||||
goto FTP_C2S_CB_END;
|
||||
}
|
||||
|
||||
char *pasv_msg = NULL;
|
||||
size_t pack_len = pasv_pack(r_fp, &pasv_msg);
|
||||
if ( ! pack_len){
|
||||
debug(LOG_ERR, "error: ftp proxy replace failed!");
|
||||
SAFE_FREE(pasv_msg);
|
||||
goto FTP_C2S_CB_END;
|
||||
}
|
||||
|
||||
#ifdef FTP_P_DEBUG
|
||||
debug(LOG_DEBUG, "ftp pack result:%s", pasv_msg);
|
||||
#endif //FTP_P_DEBUG
|
||||
|
||||
set_ftp_data_proxy_tunnel(p->proxy_name, local_fp, r_fp);
|
||||
evbuffer_add(dst, pasv_msg, pack_len);
|
||||
SAFE_FREE(pasv_msg);
|
||||
} else {
|
||||
evbuffer_add(dst, buf, read_n);
|
||||
}
|
||||
|
||||
FTP_C2S_CB_END:
|
||||
SAFE_FREE(buf);
|
||||
free_ftp_pasv(local_fp);
|
||||
return;
|
||||
}
|
||||
|
||||
void ftp_proxy_s2c_cb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
tcp_proxy_s2c_cb(bev, ctx);
|
||||
}
|
||||
|
||||
static struct ftp_pasv *pasv_unpack(char *data)
|
||||
{
|
||||
char cd_buf[4] = {0};
|
||||
snprintf(cd_buf, 4, "%s", data);
|
||||
int code = atoi(cd_buf);
|
||||
if (code != 227 && code != 211 && code != 229)
|
||||
return NULL;
|
||||
|
||||
struct ftp_pasv *fp = new_ftp_pasv();
|
||||
assert(fp);
|
||||
|
||||
fp->code = code;
|
||||
switch(fp->code) {
|
||||
case 227:
|
||||
{
|
||||
int i = 0, ip_i = 0, port_i = 0, ip_start = 0, comma_n = 0;
|
||||
char port[2][4] = { {0}, {0} };
|
||||
for (i=0; i<strlen(data) && ip_i<IP_LEN; i++) {
|
||||
if (data[i] == '(') {
|
||||
ip_start = 1;
|
||||
continue;
|
||||
}
|
||||
if (! ip_start)
|
||||
continue;
|
||||
|
||||
if (data[i] == ')')
|
||||
break;
|
||||
|
||||
if (data[i] == ','){
|
||||
comma_n++;
|
||||
port_i = 0;
|
||||
if (comma_n < 4){
|
||||
fp->ftp_server_ip[ip_i] = '.';
|
||||
ip_i++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (comma_n >= 4 && port_i < 4) {
|
||||
port[comma_n - 4][port_i] = data[i];
|
||||
port_i++;
|
||||
continue;
|
||||
}
|
||||
fp->ftp_server_ip[ip_i] = data[i];
|
||||
ip_i++;
|
||||
}
|
||||
|
||||
fp->ftp_server_port = atoi(port[0]) * FTP_PASV_PORT_BLOCK + atoi(port[1]);
|
||||
debug(LOG_DEBUG, "ftp pasv unpack:[%s:%d]", fp->ftp_server_ip, fp->ftp_server_port);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
free_ftp_pasv(fp);
|
||||
break;
|
||||
}
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
// the value returned need FREE after using
|
||||
static size_t pasv_pack(struct ftp_pasv *fp, char **pack_p)
|
||||
{
|
||||
*pack_p = (char *)calloc(1, FTP_PRO_BUF);
|
||||
assert(*pack_p);
|
||||
size_t pack_len = 0;
|
||||
|
||||
switch (fp->code){
|
||||
case 227:
|
||||
{
|
||||
char ftp_ip[IP_LEN] = {0};
|
||||
int i =0;
|
||||
for (i=0; i<strlen(fp->ftp_server_ip) && i < IP_LEN; i++) {
|
||||
if (fp->ftp_server_ip[i] == '.') {
|
||||
ftp_ip[i] = ',';
|
||||
continue;
|
||||
}
|
||||
|
||||
ftp_ip[i] = fp->ftp_server_ip[i];
|
||||
}
|
||||
snprintf(*pack_p,
|
||||
FTP_PRO_BUF,
|
||||
"227 Entering Passive Mode (%s,%d,%d).\n",
|
||||
ftp_ip,
|
||||
fp->ftp_server_port / FTP_PASV_PORT_BLOCK,
|
||||
fp->ftp_server_port % FTP_PASV_PORT_BLOCK);
|
||||
|
||||
pack_len = strlen(*pack_p);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
debug(LOG_DEBUG, "ftp pasv protocol data not supportted in pasv_pack");
|
||||
free(*pack_p);
|
||||
break;
|
||||
}
|
||||
|
||||
return pack_len;
|
||||
}
|
||||
|
||||
// need be free after using
|
||||
static struct ftp_pasv *new_ftp_pasv()
|
||||
{
|
||||
struct ftp_pasv *fp = (struct ftp_pasv *)calloc(1, sizeof(struct ftp_pasv));
|
||||
if (! fp)
|
||||
return NULL;
|
||||
|
||||
memset(fp->ftp_server_ip, 0, IP_LEN);
|
||||
fp->ftp_server_port = -1;
|
||||
fp->code = -1;
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
// can be used to free NULL pointer also
|
||||
static void free_ftp_pasv(struct ftp_pasv *fp)
|
||||
{
|
||||
if (!fp)
|
||||
return;
|
||||
|
||||
SAFE_FREE(fp);
|
||||
fp = NULL;
|
||||
}
|
||||
311
proxy_tcp.c
Normal file
311
proxy_tcp.c
Normal file
@@ -0,0 +1,311 @@
|
||||
/* vim: set et ts=4 sts=4 sw=4 : */
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, contact: *
|
||||
* *
|
||||
* Free Software Foundation Voice: +1-617-542-5942 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
/** @file proxy_tcp.c
|
||||
@brief xfrp proxy tcp implemented
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <event2/bufferevent.h>
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/listener.h>
|
||||
#include <event2/event.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "uthash.h"
|
||||
#include "common.h"
|
||||
#include "proxy.h"
|
||||
#include "config.h"
|
||||
#include "tcpmux.h"
|
||||
#include "control.h"
|
||||
|
||||
#define BUF_LEN 2*1024
|
||||
|
||||
static int
|
||||
is_socks5(uint8_t *buf, int len)
|
||||
{
|
||||
if (len < 3)
|
||||
return 0;
|
||||
if (buf[0] != 0x05)
|
||||
return 0;
|
||||
if (buf[1] != 0x01)
|
||||
return 0;
|
||||
if (buf[2] != 0x00)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_socks5_addr(struct ring_buffer *rb, int len, int *offset, struct socks5_addr *addr)
|
||||
{
|
||||
assert(addr);
|
||||
assert(len > 0);
|
||||
memset(addr, 0, sizeof(struct socks5_addr));
|
||||
uint8_t buf[22] = {0};
|
||||
rx_ring_buffer_pop(rb, buf, 1);
|
||||
*offset = 1;
|
||||
if (buf[0] == 0x01) {
|
||||
if (len < 7)
|
||||
return 0;
|
||||
addr->type = 0x01;
|
||||
rx_ring_buffer_pop(rb, buf+1, 6);
|
||||
memcpy(addr->addr, buf+1, 4);
|
||||
memcpy(&addr->port, buf+5, 2);
|
||||
*offset = 7;
|
||||
} else if (buf[0] == 0x04) { // ipv6
|
||||
if (len < 19)
|
||||
return 0;
|
||||
addr->type = 0x04;
|
||||
rx_ring_buffer_pop(rb, buf+1, 18);
|
||||
memcpy(addr->addr, buf+1, 16);
|
||||
memcpy(&addr->port, buf+17, 2);
|
||||
*offset = 19;
|
||||
} else if (buf[0] == 0x03) { // domain
|
||||
if (len < 2)
|
||||
return 0;
|
||||
rx_ring_buffer_pop(rb, buf+1, 1);
|
||||
if (len < 2 + buf[1])
|
||||
return 0;
|
||||
addr->type = 0x03;
|
||||
rx_ring_buffer_pop(rb, buf+2, buf[1] + 2);
|
||||
memcpy(addr->addr, buf+2, buf[1]);
|
||||
memcpy(&addr->port, buf+2+buf[1], 2);
|
||||
*offset = 2 + buf[1] + 2;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct bufferevent *
|
||||
socks5_proxy_connect(struct proxy_client *client, struct socks5_addr *addr)
|
||||
{
|
||||
struct bufferevent *bev = NULL;
|
||||
// check addr's type
|
||||
switch(addr->type) {
|
||||
case 0x01: // ipv4
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = addr->port;
|
||||
memcpy(&sin.sin_addr, addr->addr, 4);
|
||||
// print addr->addr in ipv4 format
|
||||
char ip[INET_ADDRSTRLEN] = {0};
|
||||
inet_ntop(AF_INET, addr->addr, ip, INET_ADDRSTRLEN);
|
||||
debug(LOG_DEBUG, "socks5_proxy_connect, type: %d, ip: %s, port: %d", addr->type, ip, ntohs(addr->port));
|
||||
bev = bufferevent_socket_new(client->base, -1, BEV_OPT_CLOSE_ON_FREE);
|
||||
if (!bev) {
|
||||
debug(LOG_ERR, "socks5_proxy_connect failed, type: %d", addr->type);
|
||||
return NULL;
|
||||
}
|
||||
if (bufferevent_socket_connect(bev, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
|
||||
debug(LOG_ERR, "socks5_proxy_connect failed, type: %d", addr->type);
|
||||
bufferevent_free(bev);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x03: // domain
|
||||
// connect domain by bufferevent_socket_connect_hostname function
|
||||
bev = bufferevent_socket_new(client->base, -1, BEV_OPT_CLOSE_ON_FREE);
|
||||
if (!bev) {
|
||||
debug(LOG_ERR, "socks5_proxy_connect failed, type: %d", addr->type);
|
||||
return NULL;
|
||||
}
|
||||
if (bufferevent_socket_connect_hostname(
|
||||
bev, get_main_control()->dnsbase, AF_INET, (char *)addr->addr, ntohs(addr->port)) < 0) {
|
||||
debug(LOG_ERR, "socks5_proxy_connect failed, type: %d", addr->type);
|
||||
bufferevent_free(bev);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case 0x04: // ipv6
|
||||
{
|
||||
// connect target with ipv6 addr
|
||||
struct sockaddr_in6 sin6;
|
||||
memset(&sin6, 0, sizeof(sin6));
|
||||
sin6.sin6_family = AF_INET6;
|
||||
sin6.sin6_port = addr->port;
|
||||
memcpy(&sin6.sin6_addr, addr->addr, 16);
|
||||
bev = bufferevent_socket_new(client->base, -1, BEV_OPT_CLOSE_ON_FREE);
|
||||
if (!bev) {
|
||||
debug(LOG_ERR, "socks5_proxy_connect failed, type: %d", addr->type);
|
||||
return NULL;
|
||||
}
|
||||
if (bufferevent_socket_connect(bev, (struct sockaddr *)&sin6, sizeof(sin6)) < 0) {
|
||||
debug(LOG_ERR, "socks5_proxy_connect failed, type: %d", addr->type);
|
||||
bufferevent_free(bev);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
debug(LOG_ERR, "socks5_proxy_connect failed, type: %d", addr->type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bufferevent_setcb(bev, tcp_proxy_c2s_cb, NULL, xfrp_proxy_event_cb, client);
|
||||
bufferevent_enable(bev, EV_READ | EV_WRITE);
|
||||
|
||||
return bev;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
handle_ss5(struct proxy_client *client, struct ring_buffer *rb, int len)
|
||||
{
|
||||
uint32_t nret = 0;
|
||||
if (client->state == SOCKS5_ESTABLISHED) {
|
||||
assert(client->local_proxy_bev);
|
||||
tx_ring_buffer_write(client->local_proxy_bev, rb, len);
|
||||
return len;
|
||||
} else if (client->state == SOCKS5_INIT && len >= 7) {
|
||||
debug(LOG_DEBUG, "handle client ss5 handshake : SOCKS5_INIT len: %d", len);
|
||||
int offset = 0;
|
||||
if (!parse_socks5_addr(rb, len, &offset, &client->remote_addr)) {
|
||||
debug(LOG_ERR, "parse_ss5_addr failed");
|
||||
return nret;
|
||||
}
|
||||
|
||||
client->local_proxy_bev = socks5_proxy_connect(client, &client->remote_addr);
|
||||
if (client->local_proxy_bev == NULL) {
|
||||
debug(LOG_ERR, "socks5_proxy_connect failed");
|
||||
return 0;
|
||||
}
|
||||
debug(LOG_DEBUG, "socks5_proxy_connect success: offset: %d, len is %d rb size is %d",
|
||||
offset, len, rb->sz);
|
||||
|
||||
return offset;
|
||||
}
|
||||
return nret;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
handle_socks5(struct proxy_client *client, struct ring_buffer *rb, int len)
|
||||
{
|
||||
uint32_t nret = 0;
|
||||
// if client's local_bev is not NULL, then we should forward rb's data to local_bev
|
||||
if (client->state == SOCKS5_CONNECT) {
|
||||
assert(client->local_proxy_bev);
|
||||
tx_ring_buffer_write(client->local_proxy_bev, rb, len);
|
||||
return len;
|
||||
} else if (client->state == SOCKS5_INIT && len >= 3) {
|
||||
debug(LOG_DEBUG, "handle client socks5 handshake : SOCKS5_INIT len: %d", len);
|
||||
// consume rb->buf three bytes
|
||||
uint8_t buf[3] = {0};
|
||||
rx_ring_buffer_pop(rb, buf, 3);
|
||||
if (buf[0] != 0x5 || buf[1] != 0x1 || buf[2] != 0x0) {
|
||||
debug(LOG_ERR, "handle client socks5 handshake failed");
|
||||
return nret;
|
||||
}
|
||||
buf[0] = 0x5;
|
||||
buf[1] = 0x0;
|
||||
buf[2] = 0x0;
|
||||
tmux_stream_write(client->ctl_bev, buf, 3, &client->stream);
|
||||
client->state = SOCKS5_HANDSHAKE;
|
||||
return 3;
|
||||
} else if (client->state == SOCKS5_HANDSHAKE && len >= 10) {
|
||||
debug(LOG_DEBUG, "handle client socks5 request: SOCKS5_HANDSHAKE len: %d", len);
|
||||
uint8_t buf[3] = {0};
|
||||
rx_ring_buffer_pop(rb, buf, 3);
|
||||
if (!is_socks5(buf, 3)) {
|
||||
debug(LOG_ERR, "handle client socks5 request failed");
|
||||
return nret;
|
||||
}
|
||||
int offset = 0;
|
||||
if (!parse_socks5_addr(rb, len, &offset, &client->remote_addr)) {
|
||||
debug(LOG_ERR, "parse_socks5_addr failed");
|
||||
return nret;
|
||||
}
|
||||
client->local_proxy_bev = socks5_proxy_connect(client, &client->remote_addr);
|
||||
if (client->local_proxy_bev == NULL) {
|
||||
debug(LOG_ERR, "socks5_proxy_connect failed");
|
||||
return 0;
|
||||
}
|
||||
assert(len == offset+3);
|
||||
//tx_ring_buffer_write(client->local_bev, rb, len - offset);
|
||||
return len;
|
||||
} else {
|
||||
debug(LOG_ERR, "not socks5 protocol, close client");
|
||||
// close client->local_proxy_bev
|
||||
bufferevent_free(client->local_proxy_bev);
|
||||
return nret;
|
||||
}
|
||||
}
|
||||
|
||||
// read data from local service
|
||||
void tcp_proxy_c2s_cb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
struct proxy_client *client = (struct proxy_client *)ctx;
|
||||
assert(client);
|
||||
struct bufferevent *partner = client->ctl_bev;
|
||||
assert(partner);
|
||||
struct evbuffer *src = bufferevent_get_input(bev);
|
||||
size_t len = evbuffer_get_length(src);
|
||||
assert(len > 0);
|
||||
if (!c_conf->tcp_mux) {
|
||||
struct evbuffer *dst = bufferevent_get_output(partner);
|
||||
evbuffer_add_buffer(dst, src);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t *buf = (uint8_t *)malloc(len);
|
||||
assert(buf != NULL);
|
||||
memset(buf, 0, len);
|
||||
uint32_t nr = bufferevent_read(bev, buf, len);
|
||||
assert(nr == len);
|
||||
|
||||
nr = tmux_stream_write(partner, buf, len, &client->stream);
|
||||
if (nr < len) {
|
||||
debug(LOG_DEBUG, "stream_id [%d] len is %d tmux_stream_write %d data, disable read", client->stream.id, len, nr);
|
||||
bufferevent_disable(bev, EV_READ);
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
|
||||
// read data from frps
|
||||
// when tcp mux enable this function will not be used
|
||||
void tcp_proxy_s2c_cb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
struct proxy_client *client = (struct proxy_client *)ctx;
|
||||
assert(client);
|
||||
struct bufferevent *partner = client->local_proxy_bev;
|
||||
assert(partner);
|
||||
struct evbuffer *src, *dst;
|
||||
src = bufferevent_get_input(bev);
|
||||
size_t len = evbuffer_get_length(src);
|
||||
assert(len > 0);
|
||||
dst = bufferevent_get_output(partner);
|
||||
evbuffer_add_buffer(dst, src);
|
||||
}
|
||||
220
proxy_udp.c
Normal file
220
proxy_udp.c
Normal file
@@ -0,0 +1,220 @@
|
||||
/* vim: set et ts=4 sts=4 sw=4 : */
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, contact: *
|
||||
* *
|
||||
* Free Software Foundation Voice: +1-617-542-5942 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
/** @file proxy_tcp.c
|
||||
@brief xfrp proxy udp implemented
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liudf0716@gmail.com>
|
||||
*/
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "uthash.h"
|
||||
#include "common.h"
|
||||
#include "proxy.h"
|
||||
#include "config.h"
|
||||
#include "tcpmux.h"
|
||||
#include "control.h"
|
||||
|
||||
static const char base64_table[65] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
static int
|
||||
base64_encode(const uint8_t *src, int srclen, char *dst)
|
||||
{
|
||||
uint32_t ac = 0;
|
||||
int bits = 0;
|
||||
int i;
|
||||
char *cp = dst;
|
||||
|
||||
for (i = 0; i < srclen; i++) {
|
||||
ac = (ac << 8) | src[i];
|
||||
bits += 8;
|
||||
do {
|
||||
bits -= 6;
|
||||
*cp++ = base64_table[(ac >> bits) & 0x3f];
|
||||
} while (bits >= 6);
|
||||
}
|
||||
if (bits) {
|
||||
*cp++ = base64_table[(ac << (6 - bits)) & 0x3f];
|
||||
bits -= 6;
|
||||
}
|
||||
while (bits < 0) {
|
||||
*cp++ = '=';
|
||||
bits += 2;
|
||||
}
|
||||
return cp - dst;
|
||||
}
|
||||
|
||||
static int
|
||||
base64_decode(const char *src, int srclen, uint8_t *dst)
|
||||
{
|
||||
uint32_t ac = 0;
|
||||
int bits = 0;
|
||||
int i;
|
||||
uint8_t *bp = dst;
|
||||
|
||||
for (i = 0; i < srclen; i++) {
|
||||
const char *p = strchr(base64_table, src[i]);
|
||||
|
||||
if (src[i] == '=') {
|
||||
ac = (ac << 6);
|
||||
bits += 6;
|
||||
if (bits >= 8)
|
||||
bits -= 8;
|
||||
continue;
|
||||
}
|
||||
if (p == NULL || src[i] == 0)
|
||||
return -1;
|
||||
ac = (ac << 6) | (p - base64_table);
|
||||
bits += 6;
|
||||
if (bits >= 8) {
|
||||
bits -= 8;
|
||||
*bp++ = (uint8_t)(ac >> bits);
|
||||
}
|
||||
}
|
||||
if (ac & ((1 << bits) - 1))
|
||||
return -1;
|
||||
return bp - dst;
|
||||
}
|
||||
|
||||
static void
|
||||
evutil_base64_decode(struct evbuffer *src, struct evbuffer *dst)
|
||||
{
|
||||
uint8_t dbuff[1500] = {0};
|
||||
size_t len = evbuffer_get_length(src);
|
||||
char *buf = (char *)malloc(len);
|
||||
assert(buf != NULL);
|
||||
memset(buf, 0, len);
|
||||
evbuffer_remove(src, buf, len);
|
||||
int decode_len = base64_decode(buf, len, dbuff);
|
||||
assert(decode_len > 0 && decode_len < 1500);
|
||||
evbuffer_add(dst, dbuff, decode_len);
|
||||
free(buf);
|
||||
}
|
||||
|
||||
static void
|
||||
evutil_base64_encode(struct evbuffer *src, struct evbuffer *dst)
|
||||
{
|
||||
char ebuff[2048] = {0}; // 2048 is enough for base64 encode
|
||||
size_t len = evbuffer_get_length(src);
|
||||
uint8_t *buf = (uint8_t *)malloc(len);
|
||||
assert(buf != NULL);
|
||||
memset(buf, 0, len);
|
||||
evbuffer_remove(src, buf, len);
|
||||
int encode_len = base64_encode(buf, len, ebuff);
|
||||
assert(encode_len > 0 && encode_len < 2048);
|
||||
evbuffer_add(dst, ebuff, encode_len);
|
||||
free(buf);
|
||||
}
|
||||
|
||||
void
|
||||
handle_udp_packet(struct udp_packet *udp_pkt, struct proxy_client *client)
|
||||
{
|
||||
// debase64 of udp_pkt->content
|
||||
struct evbuffer *base64_input = evbuffer_new();
|
||||
size_t content_len = strlen(udp_pkt->content);
|
||||
evbuffer_add(base64_input, udp_pkt->content, content_len);
|
||||
struct evbuffer *base64_output = evbuffer_new();
|
||||
|
||||
evutil_base64_decode(base64_input, base64_output);
|
||||
evbuffer_free(base64_input);
|
||||
|
||||
// send buf content to local_proxy_bev
|
||||
struct bufferevent *local_proxy_bev = client->local_proxy_bev;
|
||||
assert(local_proxy_bev != NULL);
|
||||
// according to client proxy service's local address and port, send buf to local_proxy_bev
|
||||
assert(client->ps);
|
||||
// if client->ps->local_addr is domain, need to resolve it
|
||||
struct sockaddr_in local_addr;
|
||||
memset(&local_addr, 0, sizeof(local_addr));
|
||||
local_addr.sin_family = AF_INET;
|
||||
local_addr.sin_port = htons(client->ps->local_port);
|
||||
if (inet_pton(AF_INET, client->ps->local_ip, &local_addr.sin_addr) <= 0) {
|
||||
// domain
|
||||
struct hostent *host = gethostbyname(client->ps->local_ip);
|
||||
assert(host != NULL);
|
||||
if (host == NULL) {
|
||||
debug(LOG_ERR, "gethostbyname %s failed", client->ps->local_ip);
|
||||
evbuffer_free(base64_output);
|
||||
return;
|
||||
}
|
||||
memcpy(&local_addr.sin_addr, host->h_addr, host->h_length);
|
||||
}
|
||||
|
||||
// send buf to local_proxy_bev
|
||||
struct evbuffer *dst = bufferevent_get_output(local_proxy_bev);
|
||||
evbuffer_add_buffer(dst, base64_output);
|
||||
evbuffer_free(base64_output);
|
||||
}
|
||||
|
||||
void
|
||||
udp_proxy_c2s_cb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
struct proxy_client *client = (struct proxy_client *)ctx;
|
||||
assert(client);
|
||||
struct bufferevent *partner = client->ctl_bev;
|
||||
assert(partner);
|
||||
struct evbuffer *src = bufferevent_get_input(bev);
|
||||
|
||||
// encode src to base64
|
||||
struct evbuffer *base64_output = evbuffer_new();
|
||||
evutil_base64_encode(src, base64_output);
|
||||
evbuffer_free(src);
|
||||
|
||||
// convert base64_output to udp_packet and json marshal
|
||||
struct udp_packet *udp_pkt = (struct udp_packet *)malloc(sizeof(struct udp_packet));
|
||||
assert(udp_pkt != NULL);
|
||||
memset(udp_pkt, 0, sizeof(struct udp_packet));
|
||||
udp_pkt->content = evbuffer_pullup(base64_output, -1);
|
||||
udp_pkt->raddr = (struct udp_addr *)malloc(sizeof(struct udp_addr));
|
||||
assert(udp_pkt->raddr != NULL);
|
||||
memset(udp_pkt->raddr, 0, sizeof(struct udp_addr));
|
||||
udp_pkt->raddr->addr = client->ps->local_ip;
|
||||
udp_pkt->raddr->port = client->ps->local_port;
|
||||
char *buf = NULL;
|
||||
new_udp_packet_marshal(udp_pkt, &buf);
|
||||
size_t len = strlen(buf);
|
||||
free(udp_pkt->raddr);
|
||||
free(udp_pkt);
|
||||
|
||||
if (!c_conf->tcp_mux) {
|
||||
struct evbuffer *dst = bufferevent_get_output(partner);
|
||||
evbuffer_add(dst, buf, len);
|
||||
free(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t nr = tmux_stream_write(partner, buf, len, &client->stream);
|
||||
if (nr < len) {
|
||||
debug(LOG_DEBUG, "stream_id [%d] len is %d tmux_stream_write %d data, disable read", client->stream.id, len, nr);
|
||||
bufferevent_disable(bev, EV_READ);
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
|
||||
void
|
||||
udp_proxy_s2c_cb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
struct proxy_client *client = (struct proxy_client *)ctx;
|
||||
assert(client);
|
||||
}
|
||||
52
session.c
52
session.c
@@ -1,52 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include "uthash.h"
|
||||
#include "session.h"
|
||||
#include "version.h"
|
||||
#include "debug.h"
|
||||
#include "frame.h"
|
||||
|
||||
uint32_t *sid_index = NULL;
|
||||
|
||||
// need free
|
||||
uint32_t *init_sid_index()
|
||||
{
|
||||
if (NULL == sid_index) {
|
||||
sid_index = (uint32_t *)calloc(1, sizeof(uint32_t));
|
||||
if (NULL == sid_index)
|
||||
return sid_index;
|
||||
|
||||
#ifdef CLIENT_V
|
||||
*sid_index = 1;
|
||||
#elif SERVER
|
||||
*sid_index = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
*sid_index += 2; //xfrp client session id start from 3
|
||||
return sid_index;
|
||||
}
|
||||
|
||||
uint32_t get_current_sid_index()
|
||||
{
|
||||
if (NULL == sid_index) {
|
||||
return *init_sid_index();
|
||||
}
|
||||
|
||||
return *sid_index;
|
||||
}
|
||||
|
||||
uint32_t new_sid()
|
||||
{
|
||||
if (NULL == sid_index) {
|
||||
init_sid_index();
|
||||
return get_current_sid_index();
|
||||
}
|
||||
|
||||
*sid_index += 2;
|
||||
return *sid_index;
|
||||
}
|
||||
11
session.h
11
session.h
@@ -1,11 +0,0 @@
|
||||
#ifndef _SESSION_H_
|
||||
#define _SESSION_H_
|
||||
|
||||
#include "uthash.h"
|
||||
#include "common.h"
|
||||
|
||||
uint32_t *init_sid_index();
|
||||
uint32_t get_current_sid_index();
|
||||
uint32_t new_sid();
|
||||
|
||||
#endif //_SESSION_H_
|
||||
16
systemd/xfrpc.service
Normal file
16
systemd/xfrpc.service
Normal file
@@ -0,0 +1,16 @@
|
||||
# 1. put xfrpc and xfrpc.ini under /usr/local/xfrpc/
|
||||
# 2. put this file (xfrpc.service) at /etc/systemd/system
|
||||
# 3. run `sudo systemctl daemon-reload && sudo systemctl enable xfrpc && sudo systemctl start xfrpc`
|
||||
# Then we can manage xfrpc with `sudo service xfrpc {start|stop|restart|status}`
|
||||
|
||||
|
||||
[Unit]
|
||||
Description=frp c language client
|
||||
Wants=network-online.target
|
||||
After=network.target network-online.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/xfrpc/xfrpc -c /usr/local/xfrpc/xfrpc.ini -f -d 0
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
211
tcp_redir.c
Normal file
211
tcp_redir.c
Normal file
@@ -0,0 +1,211 @@
|
||||
/* vim: set et ts=4 sts=4 sw=4 : */
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, contact: *
|
||||
* *
|
||||
* Free Software Foundation Voice: +1-617-542-5942 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
/** @file tcp_redir.c
|
||||
@brief xfrp tcp redirect service implemented
|
||||
@author Copyright (C) 2023 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "debug.h"
|
||||
#include "config.h"
|
||||
#include "utils.h"
|
||||
#include "tcp_redir.h"
|
||||
|
||||
|
||||
// define a struct for tcp_redir which include proxy_service and event_base
|
||||
struct tcp_redir_service {
|
||||
struct event_base *base;
|
||||
struct proxy_service *ps;
|
||||
struct sockaddr_in server_addr;
|
||||
};
|
||||
|
||||
static struct bufferevent *current_bev = NULL; // Global variable to hold the current connection
|
||||
|
||||
// define a callback function for read event
|
||||
static void read_cb(struct bufferevent *bev, void *arg)
|
||||
{
|
||||
struct bufferevent *bev_out = (struct bufferevent *)arg;
|
||||
struct evbuffer *input = bufferevent_get_input(bev);
|
||||
struct evbuffer *output = bufferevent_get_output(bev_out);
|
||||
evbuffer_add_buffer(output, input);
|
||||
}
|
||||
|
||||
// define a callback function for event event
|
||||
static void event_cb(struct bufferevent *bev, short events, void *arg)
|
||||
{
|
||||
struct bufferevent *partner = (struct bufferevent *)arg;
|
||||
if (events & BEV_EVENT_CONNECTED) {
|
||||
debug(LOG_INFO, "connected");
|
||||
} else if (events & BEV_EVENT_ERROR) {
|
||||
debug(LOG_ERR, "connection error");
|
||||
bufferevent_free(bev);
|
||||
bufferevent_free(partner);
|
||||
current_bev = NULL;
|
||||
} else if (events & BEV_EVENT_EOF) {
|
||||
debug(LOG_INFO, "connection closed");
|
||||
bufferevent_free(bev);
|
||||
bufferevent_free(partner);
|
||||
current_bev = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// define a callback function for accept event
|
||||
static void accept_cb(struct evconnlistener *listener, evutil_socket_t fd,
|
||||
struct sockaddr *address, int socklen, void *arg)
|
||||
{
|
||||
if (current_bev) {
|
||||
// Already have a connection, reject new connection
|
||||
debug(LOG_INFO, "Rejecting new connection. Only one connection allowed at a time.");
|
||||
evutil_closesocket(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
// the argument is the proxy_service
|
||||
struct tcp_redir_service *trs = (struct tcp_redir_service *)arg;
|
||||
struct event_base *base = trs->base;
|
||||
|
||||
// read the data from the local port
|
||||
struct bufferevent *bev_in = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
|
||||
if (!bev_in) {
|
||||
debug(LOG_ERR, "create bufferevent for local port failed!");
|
||||
evutil_closesocket(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
// connect to the remote xfrpc service
|
||||
struct bufferevent *bev_out = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
|
||||
if (!bev_out) {
|
||||
debug(LOG_ERR, "create bufferevent for remote xfrps service failed!");
|
||||
bufferevent_free(bev_in);
|
||||
return;
|
||||
}
|
||||
|
||||
// connect to the remote port
|
||||
if (bufferevent_socket_connect(bev_out, (struct sockaddr *)&(trs->server_addr), sizeof(trs->server_addr)) < 0) {
|
||||
debug(LOG_ERR, "connect to remote port failed! %s", strerror(errno));
|
||||
bufferevent_free(bev_in);
|
||||
bufferevent_free(bev_out);
|
||||
return;
|
||||
}
|
||||
debug(LOG_INFO, "connect to remote xfrps service [%s:%d] success!",
|
||||
get_common_config()->server_addr, trs->ps->remote_port);
|
||||
|
||||
bufferevent_setcb(bev_in, read_cb, NULL, event_cb, (void *)bev_out);
|
||||
bufferevent_setcb(bev_out, read_cb, NULL, event_cb, (void *)bev_in);
|
||||
bufferevent_enable(bev_in, EV_READ|EV_WRITE);
|
||||
bufferevent_enable(bev_out, EV_READ|EV_WRITE);
|
||||
|
||||
current_bev = bev_in;
|
||||
|
||||
debug(LOG_INFO, "connect to remote port success!");
|
||||
return;
|
||||
}
|
||||
|
||||
// define a thread worker function for tcp_redir
|
||||
static void *tcp_redir_worker(void *arg)
|
||||
{
|
||||
struct proxy_service *ps = (struct proxy_service *)arg;
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
// the worker is based on libevent and bufferevent
|
||||
// it listens on the local port and forward the data to the remote port
|
||||
// the local port and remote port are defined in the proxy_service
|
||||
// the proxy_service as argument is passed to the worker function
|
||||
|
||||
// create a event_base
|
||||
struct evconnlistener *listener;
|
||||
struct event_base *base = event_base_new();
|
||||
if (!base) {
|
||||
debug(LOG_ERR, "create event base failed!");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// define listen address and port
|
||||
struct sockaddr_in sin;
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = htons(ps->local_port);
|
||||
sin.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
struct tcp_redir_service trs;
|
||||
trs.base = base;
|
||||
trs.ps = ps;
|
||||
trs.server_addr.sin_family = AF_INET;
|
||||
trs.server_addr.sin_port = htons(ps->remote_port);
|
||||
// if c_conf->server_addr is ip address, use inet_addr to convert it
|
||||
// if c_conf->server_addr is domain name, use gethostbyname to convert it
|
||||
if (is_valid_ip_address(c_conf->server_addr))
|
||||
trs.server_addr.sin_addr.s_addr = inet_addr(c_conf->server_addr);
|
||||
else {
|
||||
struct hostent *host = gethostbyname(c_conf->server_addr);
|
||||
if (!host) {
|
||||
debug(LOG_ERR, "gethostbyname failed!");
|
||||
exit(1);
|
||||
}
|
||||
// only support ipv4
|
||||
if (host->h_addrtype != AF_INET) {
|
||||
debug(LOG_ERR, "only support ipv4!");
|
||||
exit(1);
|
||||
}
|
||||
trs.server_addr.sin_addr.s_addr = *(unsigned long *)host->h_addr_list[0];
|
||||
}
|
||||
|
||||
// create a listener
|
||||
listener = evconnlistener_new_bind(base, accept_cb, (void *)&trs,
|
||||
LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, -1, (struct sockaddr *)&sin, sizeof(sin));
|
||||
if (!listener) {
|
||||
debug(LOG_ERR, "create listener failed!");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// start the event loop
|
||||
event_base_dispatch(base);
|
||||
|
||||
// free the listener
|
||||
evconnlistener_free(listener);
|
||||
// free the event base
|
||||
event_base_free(base);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void start_tcp_redir_service(struct proxy_service *ps)
|
||||
{
|
||||
// create a thread
|
||||
pthread_t tid;
|
||||
if (pthread_create(&tid, NULL, tcp_redir_worker, (void *)ps) != 0) {
|
||||
debug(LOG_ERR, "create tcp_redir worker thread failed!");
|
||||
exit(1);
|
||||
}
|
||||
debug(LOG_INFO, "create tcp_redir worker thread success!");
|
||||
|
||||
// detach the thread
|
||||
if (pthread_detach(tid) != 0) {
|
||||
debug(LOG_ERR, "detach tcp_redir worker thread failed!");
|
||||
exit(1);
|
||||
}
|
||||
debug(LOG_INFO, "detach tcp_redir worker thread success!");
|
||||
|
||||
return;
|
||||
}
|
||||
8
tcp_redir.h
Normal file
8
tcp_redir.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef _TCP_REDIR_H_
|
||||
#define _TCP_REDIR_H_
|
||||
|
||||
#include "proxy.h"
|
||||
|
||||
void start_tcp_redir_service(struct proxy_service *proxy);
|
||||
|
||||
#endif
|
||||
659
tcpmux.c
Normal file
659
tcpmux.c
Normal file
@@ -0,0 +1,659 @@
|
||||
/* vim: set et ts=4 sts=4 sw=4 : */
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, contact: *
|
||||
* *
|
||||
* Free Software Foundation Voice: +1-617-542-5942 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
/** @file tcpmux.c
|
||||
@brief xfrp tcp mux implemented
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "tcpmux.h"
|
||||
#include "client.h"
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "control.h"
|
||||
#include "proxy.h"
|
||||
|
||||
static uint8_t proto_version = 0;
|
||||
static uint8_t remote_go_away;
|
||||
static uint8_t local_go_away;
|
||||
static uint32_t g_session_id = 1;
|
||||
static struct tmux_stream *cur_stream = NULL;
|
||||
static struct tmux_stream *all_stream;
|
||||
|
||||
|
||||
void
|
||||
add_stream(struct tmux_stream *stream)
|
||||
{
|
||||
HASH_ADD_INT(all_stream, id, stream);
|
||||
}
|
||||
|
||||
void
|
||||
del_stream(uint32_t id)
|
||||
{
|
||||
if (!all_stream) return;
|
||||
|
||||
struct tmux_stream *stream = get_stream_by_id(id);
|
||||
if (stream)
|
||||
HASH_DEL(all_stream, stream);
|
||||
}
|
||||
|
||||
void
|
||||
clear_stream()
|
||||
{
|
||||
if (!all_stream) return;
|
||||
|
||||
HASH_CLEAR(hh, all_stream);
|
||||
all_stream = NULL;
|
||||
}
|
||||
|
||||
struct tmux_stream *
|
||||
get_stream_by_id(uint32_t id)
|
||||
{
|
||||
if (!all_stream) return NULL;
|
||||
|
||||
struct tmux_stream *stream = NULL;
|
||||
HASH_FIND_INT(all_stream, &id, stream);
|
||||
return stream;
|
||||
}
|
||||
|
||||
struct tmux_stream *
|
||||
get_cur_stream()
|
||||
{
|
||||
return cur_stream;
|
||||
}
|
||||
|
||||
void
|
||||
set_cur_stream(struct tmux_stream *stream)
|
||||
{
|
||||
cur_stream = stream;
|
||||
}
|
||||
|
||||
void
|
||||
init_tmux_stream(struct tmux_stream *stream, uint32_t id, enum tcp_mux_state state)
|
||||
{
|
||||
stream->id = id;
|
||||
stream->state = state;
|
||||
stream->recv_window = MAX_STREAM_WINDOW_SIZE;
|
||||
stream->send_window = MAX_STREAM_WINDOW_SIZE;
|
||||
|
||||
memset(&stream->tx_ring, 0, sizeof(struct ring_buffer));
|
||||
memset(&stream->rx_ring, 0, sizeof(struct ring_buffer));
|
||||
|
||||
add_stream(stream);
|
||||
};
|
||||
|
||||
int
|
||||
validate_tcp_mux_protocol(struct tcp_mux_header *tmux_hdr)
|
||||
{
|
||||
if (tmux_hdr->version != proto_version) return 0;
|
||||
|
||||
if (tmux_hdr->type > GO_AWAY) return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
tcp_mux_encode(enum tcp_mux_type type, enum tcp_mux_flag flags, uint32_t stream_id, uint32_t length, struct tcp_mux_header *tmux_hdr)
|
||||
{
|
||||
assert(tmux_hdr);
|
||||
tmux_hdr->version = proto_version;
|
||||
tmux_hdr->type = type;
|
||||
tmux_hdr->flags = htons(flags);
|
||||
tmux_hdr->stream_id = htonl(stream_id);
|
||||
tmux_hdr->length = length?htonl(length):0;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
tcp_mux_flag()
|
||||
{
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
return c_conf->tcp_mux;
|
||||
}
|
||||
|
||||
void
|
||||
reset_session_id() {
|
||||
g_session_id = 1;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
get_next_session_id() {
|
||||
uint32_t id = g_session_id;
|
||||
g_session_id += 2;
|
||||
return id;
|
||||
}
|
||||
|
||||
static void
|
||||
tcp_mux_send_win_update(struct bufferevent *bout, enum tcp_mux_flag flags, uint32_t stream_id, uint32_t delta)
|
||||
{
|
||||
struct tcp_mux_header tmux_hdr;
|
||||
memset(&tmux_hdr, 0, sizeof(tmux_hdr));
|
||||
tcp_mux_encode(WINDOW_UPDATE, flags, stream_id, delta, &tmux_hdr);
|
||||
bufferevent_write(bout, (uint8_t *)&tmux_hdr, sizeof(tmux_hdr));
|
||||
}
|
||||
|
||||
void
|
||||
tcp_mux_send_win_update_syn(struct bufferevent *bout, uint32_t stream_id)
|
||||
{
|
||||
if (!tcp_mux_flag()) return;
|
||||
|
||||
tcp_mux_send_win_update(bout, SYN, stream_id, 0);
|
||||
}
|
||||
|
||||
void
|
||||
tcp_mux_send_win_update_ack(struct bufferevent *bout, uint32_t stream_id, uint32_t delta)
|
||||
{
|
||||
if (!tcp_mux_flag()) return;
|
||||
|
||||
tcp_mux_send_win_update(bout, ZERO, stream_id, 0);
|
||||
}
|
||||
|
||||
void
|
||||
tcp_mux_send_win_update_fin(struct bufferevent *bout, uint32_t stream_id)
|
||||
{
|
||||
if (!tcp_mux_flag()) return;
|
||||
|
||||
tcp_mux_send_win_update(bout, FIN, stream_id, 0);
|
||||
}
|
||||
|
||||
void
|
||||
tcp_mux_send_win_update_rst(struct bufferevent *bout, uint32_t stream_id)
|
||||
{
|
||||
if (!tcp_mux_flag()) return;
|
||||
|
||||
tcp_mux_send_win_update(bout, RST, stream_id, 0);
|
||||
}
|
||||
void
|
||||
tcp_mux_send_data(struct bufferevent *bout, uint16_t flags, uint32_t stream_id, uint32_t length)
|
||||
{
|
||||
if (!tcp_mux_flag()) return;
|
||||
|
||||
struct tcp_mux_header tmux_hdr;
|
||||
memset(&tmux_hdr, 0, sizeof(tmux_hdr));
|
||||
tcp_mux_encode(DATA, flags, stream_id, length, &tmux_hdr);
|
||||
//debug(LOG_DEBUG, "tcp mux [%d] send data len : %d", stream_id, length);
|
||||
bufferevent_write(bout, (uint8_t *)&tmux_hdr, sizeof(tmux_hdr));
|
||||
}
|
||||
|
||||
void
|
||||
tcp_mux_send_ping(struct bufferevent *bout, uint32_t ping_id)
|
||||
{
|
||||
if (!tcp_mux_flag()) return;
|
||||
|
||||
struct tcp_mux_header tmux_hdr;
|
||||
memset(&tmux_hdr, 0, sizeof(tmux_hdr));
|
||||
tcp_mux_encode(PING, SYN, 0, ping_id, &tmux_hdr);
|
||||
//debug(LOG_DEBUG, "tcp mux send ping syn : %d", ping_id);
|
||||
bufferevent_write(bout, (uint8_t *)&tmux_hdr, sizeof(tmux_hdr));
|
||||
}
|
||||
|
||||
static void
|
||||
tcp_mux_handle_ping(struct bufferevent *bout, uint32_t ping_id)
|
||||
{
|
||||
if (!tcp_mux_flag()) return;
|
||||
|
||||
struct tcp_mux_header tmux_hdr;
|
||||
memset(&tmux_hdr, 0, sizeof(tmux_hdr));
|
||||
tcp_mux_encode(PING, ACK, 0, ping_id, &tmux_hdr);
|
||||
//debug(LOG_DEBUG, "tcp mux send ping ack : %d", ping_id);
|
||||
bufferevent_write(bout, (uint8_t *)&tmux_hdr, sizeof(tmux_hdr));
|
||||
}
|
||||
|
||||
static void
|
||||
tcp_mux_send_go_away(struct bufferevent *bout, uint32_t reason)
|
||||
{
|
||||
if (!tcp_mux_flag()) return;
|
||||
|
||||
struct tcp_mux_header tmux_hdr;
|
||||
memset(&tmux_hdr, 0, sizeof(tmux_hdr));
|
||||
tcp_mux_encode(GO_AWAY, 0, 0, reason, &tmux_hdr);
|
||||
//debug(LOG_DEBUG, "tcp mux send ping ack : %d", ping_id);
|
||||
bufferevent_write(bout, (uint8_t *)&tmux_hdr, sizeof(tmux_hdr));
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
process_flags(uint16_t flags, struct tmux_stream *stream)
|
||||
{
|
||||
uint32_t close_stream = 0;
|
||||
if ( (flags&ACK) == ACK ) {
|
||||
if (stream->state == SYN_SEND)
|
||||
stream->state = ESTABLISHED;
|
||||
} else if ( (flags&FIN) == FIN ) {
|
||||
switch(stream->state) {
|
||||
case SYN_SEND:
|
||||
case SYN_RECEIVED:
|
||||
case ESTABLISHED:
|
||||
stream->state = REMOTE_CLOSE;
|
||||
break;
|
||||
case LOCAL_CLOSE:
|
||||
stream->state = CLOSED;
|
||||
close_stream = 1;
|
||||
break;
|
||||
default:
|
||||
debug(LOG_ERR, "unexpected FIN flag in state %d", stream->state);
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
} else if ( (flags&RST) == RST ) {
|
||||
stream->state = RESET;
|
||||
close_stream = 1;
|
||||
}
|
||||
|
||||
if (close_stream) {
|
||||
debug(LOG_DEBUG, "free stream %d", stream->id);
|
||||
del_proxy_client_by_stream_id(stream->id);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
get_send_flags(struct tmux_stream *stream)
|
||||
{
|
||||
uint16_t flags = 0;
|
||||
|
||||
switch (stream->state) {
|
||||
case INIT:
|
||||
flags |= SYN;
|
||||
stream->state = SYN_SEND;
|
||||
break;
|
||||
case SYN_RECEIVED:
|
||||
flags |= ACK;
|
||||
stream->state = ESTABLISHED;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
void
|
||||
send_window_update(struct bufferevent *bout, struct tmux_stream *stream, uint32_t length)
|
||||
{
|
||||
uint32_t max = MAX_STREAM_WINDOW_SIZE;
|
||||
uint32_t delta = (max - length) - stream->recv_window;
|
||||
|
||||
uint16_t flags = get_send_flags(stream);
|
||||
|
||||
if (delta < max/2 && flags == 0)
|
||||
return;
|
||||
|
||||
stream->recv_window += delta;
|
||||
tcp_mux_send_win_update(bout, flags, stream->id, delta);
|
||||
//debug(LOG_DEBUG, "send window update: flags %d, stream_id %d delta %d, recv_window %u length %u",
|
||||
// flags, stream->id, delta, stream->recv_window, length);
|
||||
}
|
||||
|
||||
int
|
||||
rx_ring_buffer_pop(struct ring_buffer *ring, uint8_t *data, uint32_t len)
|
||||
{
|
||||
assert(ring->sz >= len);
|
||||
assert(data);
|
||||
|
||||
uint32_t i = 0;
|
||||
while(i < len) {
|
||||
data[i] = ring->data[ring->cur++];
|
||||
if (ring->cur == RBUF_SIZE)
|
||||
ring->cur = 0;
|
||||
i++;
|
||||
ring->sz--;
|
||||
}
|
||||
|
||||
assert(i == len);
|
||||
return len;
|
||||
}
|
||||
|
||||
static int
|
||||
process_data(struct tmux_stream *stream, uint32_t length, uint16_t flags,
|
||||
void (*fn)(uint8_t *, int, void *), void *param)
|
||||
{
|
||||
if(!stream){
|
||||
return 0;
|
||||
}
|
||||
uint32_t id = stream->id;
|
||||
|
||||
if (!process_flags(flags, stream)) return 0;
|
||||
|
||||
if(!get_stream_by_id(id)){
|
||||
return length;
|
||||
}
|
||||
|
||||
if (length > stream->recv_window) {
|
||||
debug(LOG_ERR, "receive window exceed (remain %d, recv %d)", stream->recv_window, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
stream->recv_window -= length;
|
||||
|
||||
uint32_t nret = 0;
|
||||
struct proxy_client *pc = (struct proxy_client *)param;
|
||||
if (!pc || (pc && !pc->local_proxy_bev && !is_socks5_proxy(pc->ps))) {
|
||||
uint8_t *data = (uint8_t *)calloc(length, 1);
|
||||
nret = rx_ring_buffer_pop(&stream->rx_ring, data, length);
|
||||
fn(data, length, pc);
|
||||
free(data);
|
||||
} else if (is_socks5_proxy(pc->ps)) {
|
||||
// if pc's type is socks5, we should send data to socks5 client
|
||||
nret = handle_ss5(pc, &stream->rx_ring, length);
|
||||
} else {
|
||||
nret = tx_ring_buffer_write(pc->local_proxy_bev, &stream->rx_ring, length);
|
||||
|
||||
}
|
||||
|
||||
if (nret != length) {
|
||||
debug(LOG_INFO, "send data to local proxy not equal, nret %d, length %d", nret, length);
|
||||
}
|
||||
|
||||
struct bufferevent *bout = get_main_control()->connect_bev;
|
||||
send_window_update(bout, stream, nret);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
static int
|
||||
incr_send_window(struct bufferevent *bev, struct tcp_mux_header *tmux_hdr, uint16_t flags, struct tmux_stream *stream)
|
||||
{
|
||||
if(!stream){
|
||||
return 0;
|
||||
}
|
||||
uint32_t id = stream->id;
|
||||
|
||||
if (!process_flags(flags, stream))
|
||||
return 0;
|
||||
|
||||
if(!get_stream_by_id(id)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t length = ntohl(tmux_hdr->length);
|
||||
|
||||
if (stream->send_window == 0) bufferevent_enable(bev, EV_READ);
|
||||
stream->send_window += length;
|
||||
//debug(LOG_DEBUG, "incr_send_window : stream_id %d length %d send_window %d",
|
||||
// stream->id, length, stream->send_window);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
incoming_stream(uint32_t stream_id)
|
||||
{
|
||||
if (local_go_away) {
|
||||
struct bufferevent *bout = get_main_control()->connect_bev;
|
||||
tcp_mux_send_win_update_rst(bout, stream_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO
|
||||
// create new stream
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
handle_tcp_mux_ping(struct tcp_mux_header *tmux_hdr)
|
||||
{
|
||||
uint16_t flags = ntohs(tmux_hdr->flags);
|
||||
uint32_t ping_id = ntohl(tmux_hdr->length);
|
||||
|
||||
if ( (flags&SYN) == SYN) {
|
||||
struct bufferevent *bout = get_main_control()->connect_bev;
|
||||
tcp_mux_handle_ping(bout, ping_id);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
handle_tcp_mux_go_away(struct tcp_mux_header *tmux_hdr)
|
||||
{
|
||||
uint32_t code = ntohl(tmux_hdr->length);
|
||||
switch(code) {
|
||||
case NORMAL:
|
||||
remote_go_away = 1;
|
||||
break;
|
||||
case PROTO_ERR:
|
||||
debug(LOG_ERR, "receive protocol error go away");
|
||||
break;
|
||||
case INTERNAL_ERR:
|
||||
debug(LOG_ERR, "receive internal error go away");
|
||||
break;
|
||||
default:
|
||||
debug(LOG_ERR, "receive unexpected go away");
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
tmux_stream_read(struct bufferevent *bev, struct tmux_stream *stream, uint32_t len)
|
||||
{
|
||||
assert(stream != NULL);
|
||||
if (stream->state != ESTABLISHED) {
|
||||
debug(LOG_WARNING, "stream %d state is %d : not ESTABLISHED, discard its data len %d", stream->id, stream->state, len);
|
||||
}
|
||||
|
||||
return rx_ring_buffer_read(bev, &stream->rx_ring, len);
|
||||
}
|
||||
|
||||
int
|
||||
handle_tcp_mux_stream(struct tcp_mux_header *tmux_hdr, handle_data_fn_t fn)
|
||||
{
|
||||
uint32_t stream_id = ntohl(tmux_hdr->stream_id);
|
||||
uint16_t flags = ntohs(tmux_hdr->flags);
|
||||
|
||||
//debug(LOG_DEBUG, "handle_tcp_mux_stream stream_id %d type %d flags %d", stream_id, tmux_hdr->type, flags);
|
||||
|
||||
if ( (flags&SYN) == SYN) {
|
||||
debug(LOG_INFO, "!!!! as xfrpc, it should not be here %d", stream_id);
|
||||
if (!incoming_stream(stream_id))
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct tmux_stream *stream = get_stream_by_id(stream_id);
|
||||
|
||||
if(!stream){
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct proxy_client *pc = get_proxy_client(stream_id);
|
||||
|
||||
if (tmux_hdr->type == WINDOW_UPDATE) {
|
||||
struct bufferevent *bev = pc?pc->local_proxy_bev: get_main_control()->connect_bev;
|
||||
if (!incr_send_window(bev, tmux_hdr, flags, stream)) {
|
||||
struct bufferevent *bout = get_main_control()->connect_bev;
|
||||
tcp_mux_send_go_away(bout, PROTO_ERR);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct bufferevent *bout = get_main_control()->connect_bev;
|
||||
if (stream->state != ESTABLISHED) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t length = ntohl(tmux_hdr->length);
|
||||
if (!process_data(stream, length, flags, fn, (void *)pc)) {
|
||||
tcp_mux_send_go_away(bout, PROTO_ERR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
static int
|
||||
tx_ring_buffer_append(struct ring_buffer *ring, uint8_t *data, uint32_t len)
|
||||
{
|
||||
uint32_t left = WBUF_SIZE - ring->sz;
|
||||
assert(left >= len);
|
||||
int i = 0;
|
||||
for (; i < len; i++) {
|
||||
ring->data[ring->end++] = data[i];
|
||||
if (ring->end == WBUF_SIZE) ring->end = 0;
|
||||
ring->sz++;
|
||||
if (ring->cur == ring->end) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
rx_ring_buffer_read(struct bufferevent *bev, struct ring_buffer *ring, uint32_t len)
|
||||
{
|
||||
if (ring->sz == RBUF_SIZE) {
|
||||
debug(LOG_ERR, "ring buffer is full");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t cap = RBUF_SIZE - ring->sz;
|
||||
if (len > cap) {
|
||||
debug(LOG_INFO, "prepare read data [%d] out size ring capacity [%d]", len, cap);
|
||||
len = cap;
|
||||
}
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
bufferevent_read(bev, &ring->data[ring->end++], 1);
|
||||
if (ring->end == RBUF_SIZE) ring->end = 0;
|
||||
ring->sz++;
|
||||
if (ring->cur == ring->end) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
|
||||
}
|
||||
|
||||
uint32_t
|
||||
tx_ring_buffer_write(struct bufferevent *bev, struct ring_buffer *ring, uint32_t len)
|
||||
{
|
||||
if (ring->sz == 0) {
|
||||
debug(LOG_ERR, "ring buffer is empty");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (len > ring->sz) {
|
||||
debug(LOG_INFO, "prepare write data [%d] out size ring data [%d]", len, ring->sz);
|
||||
len = ring->sz;
|
||||
}
|
||||
|
||||
uint32_t nwrite = len;
|
||||
while(len > 0) {
|
||||
bufferevent_write(bev, &ring->data[ring->cur++], 1);
|
||||
len--;
|
||||
ring->sz--;;
|
||||
if (ring->cur == WBUF_SIZE) ring->cur = 0;
|
||||
if (ring->cur == ring->end) {
|
||||
assert(ring->sz == 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return nwrite - len;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
tmux_stream_write(struct bufferevent *bev, uint8_t *data, uint32_t length, struct tmux_stream *stream)
|
||||
{
|
||||
switch(stream->state) {
|
||||
case LOCAL_CLOSE:
|
||||
case CLOSED:
|
||||
case RESET:
|
||||
debug(LOG_INFO, "stream %d state is closed", stream->id);
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
struct ring_buffer *tx_ring = &stream->tx_ring;
|
||||
uint32_t left = WBUF_SIZE - tx_ring->sz;
|
||||
if (stream->send_window == 0) {
|
||||
debug(LOG_INFO, "stream %d send_window is zero, length %d left %d", stream->id, length, left);
|
||||
tx_ring_buffer_append(tx_ring, data, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t flags = get_send_flags(stream);
|
||||
uint32_t max = length;
|
||||
struct bufferevent *bout = get_main_control()->connect_bev;
|
||||
//debug(LOG_DEBUG, "tmux_stream_write stream id %u: send_window %u tx_ring sz %u length %u",
|
||||
// stream->id, stream->send_window, tx_ring->sz, length);
|
||||
if (stream->send_window < tx_ring->sz) {
|
||||
debug(LOG_INFO, " send_window %u less than tx_ring size %u", stream->send_window, tx_ring->sz);
|
||||
max = stream->send_window;
|
||||
tcp_mux_send_data(bout, flags, stream->id, max);
|
||||
tx_ring_buffer_write(bev, tx_ring, max);
|
||||
tx_ring_buffer_append(tx_ring, data, length);
|
||||
} else if (stream->send_window < tx_ring->sz + length) {
|
||||
debug(LOG_INFO, " send_window %u less than %u", stream->send_window, tx_ring->sz+length);
|
||||
max = stream->send_window;
|
||||
tcp_mux_send_data(bout, flags, stream->id, max);
|
||||
if (tx_ring->sz > 0)
|
||||
tx_ring_buffer_write(bev, tx_ring, tx_ring->sz);
|
||||
bufferevent_write(bev, data, max - tx_ring->sz);
|
||||
tx_ring_buffer_append(tx_ring, data + max - tx_ring->sz, length + tx_ring->sz - max);
|
||||
} else {
|
||||
max = tx_ring->sz + length;
|
||||
tcp_mux_send_data(bout, flags, stream->id, max);
|
||||
if (tx_ring->sz > 0)
|
||||
tx_ring_buffer_write(bev, tx_ring, tx_ring->sz);
|
||||
bufferevent_write(bev, data, length);
|
||||
}
|
||||
|
||||
stream->send_window -= max;
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
int
|
||||
tmux_stream_close(struct bufferevent *bout, struct tmux_stream *stream)
|
||||
{
|
||||
uint8_t flag = 0;
|
||||
switch(stream->state) {
|
||||
case SYN_SEND:
|
||||
case SYN_RECEIVED:
|
||||
case ESTABLISHED:
|
||||
stream->state = LOCAL_CLOSE;
|
||||
break;
|
||||
case LOCAL_CLOSE:
|
||||
case REMOTE_CLOSE:
|
||||
flag = 1;
|
||||
stream->state = CLOSED;
|
||||
break;
|
||||
case CLOSED:
|
||||
case RESET:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t flags = get_send_flags(stream);
|
||||
flags |= FIN;
|
||||
tcp_mux_send_win_update(bout, flags, stream->id, 0);
|
||||
if (!flag) return 1;
|
||||
|
||||
debug(LOG_DEBUG, "del proxy client %d", stream->id);
|
||||
del_proxy_client_by_stream_id(stream->id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
163
tcpmux.h
Normal file
163
tcpmux.h
Normal file
@@ -0,0 +1,163 @@
|
||||
/* vim: set et ts=4 sts=4 sw=4 : */
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, contact: *
|
||||
* *
|
||||
* Free Software Foundation Voice: +1-617-542-5942 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
/** @file tcpmux.h
|
||||
@brief xfrp tcp mux header file
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
#ifndef __TCP_MUX__
|
||||
#define __TCP_MUX__
|
||||
|
||||
#include "uthash.h"
|
||||
|
||||
#define MAX_STREAM_WINDOW_SIZE 256*1024
|
||||
#define RBUF_SIZE 32*1024
|
||||
#define WBUF_SIZE 32*1024
|
||||
|
||||
|
||||
struct ring_buffer {
|
||||
uint32_t cur;
|
||||
uint32_t end;
|
||||
uint32_t sz;
|
||||
uint8_t data[RBUF_SIZE];
|
||||
};
|
||||
|
||||
enum go_away_type {
|
||||
NORMAL,
|
||||
PROTO_ERR,
|
||||
INTERNAL_ERR,
|
||||
};
|
||||
|
||||
enum tcp_mux_type {
|
||||
DATA,
|
||||
WINDOW_UPDATE,
|
||||
PING,
|
||||
GO_AWAY,
|
||||
};
|
||||
|
||||
struct tcp_mux_type_desc {
|
||||
enum tcp_mux_type type;
|
||||
char *desc;
|
||||
};
|
||||
|
||||
enum tcp_mux_flag {
|
||||
ZERO,
|
||||
SYN,
|
||||
ACK = 1<<1,
|
||||
FIN = 1<<2,
|
||||
RST = 1<<3,
|
||||
};
|
||||
|
||||
struct __attribute__((__packed__)) tcp_mux_header {
|
||||
uint8_t version;
|
||||
uint8_t type;
|
||||
uint16_t flags;
|
||||
uint32_t stream_id;
|
||||
uint32_t length;
|
||||
};
|
||||
|
||||
struct tcp_mux_flag_desc {
|
||||
enum tcp_mux_flag flag;
|
||||
char *desc;
|
||||
};
|
||||
|
||||
enum tcp_mux_state {
|
||||
INIT = 0,
|
||||
SYN_SEND,
|
||||
SYN_RECEIVED,
|
||||
ESTABLISHED,
|
||||
LOCAL_CLOSE,
|
||||
REMOTE_CLOSE,
|
||||
CLOSED,
|
||||
RESET
|
||||
};
|
||||
|
||||
struct tmux_stream {
|
||||
uint32_t id;
|
||||
uint32_t recv_window;
|
||||
uint32_t send_window;
|
||||
enum tcp_mux_state state;
|
||||
struct ring_buffer tx_ring;
|
||||
struct ring_buffer rx_ring;
|
||||
|
||||
// private arguments
|
||||
UT_hash_handle hh;
|
||||
};
|
||||
|
||||
typedef void (*handle_data_fn_t)(uint8_t *, int, void *);
|
||||
|
||||
void init_tmux_stream(struct tmux_stream *stream, uint32_t id, enum tcp_mux_state state);
|
||||
|
||||
int validate_tcp_mux_protocol(struct tcp_mux_header *tmux_hdr);
|
||||
|
||||
void send_window_update(struct bufferevent *bout, struct tmux_stream *stream, uint32_t length);
|
||||
|
||||
void tcp_mux_send_win_update_syn(struct bufferevent *bout, uint32_t stream_id);
|
||||
|
||||
void tcp_mux_send_win_update_ack(struct bufferevent *bout, uint32_t stream_id, uint32_t delta);
|
||||
|
||||
void tcp_mux_send_win_update_fin(struct bufferevent *bout, uint32_t stream_id);
|
||||
|
||||
void tcp_mux_send_win_update_rst(struct bufferevent *bout, uint32_t stream_id);
|
||||
|
||||
void tcp_mux_send_data(struct bufferevent *bout, uint16_t flags, uint32_t stream_id, uint32_t length);
|
||||
|
||||
void tcp_mux_send_ping(struct bufferevent *bout, uint32_t ping_id);
|
||||
|
||||
uint32_t get_next_session_id();
|
||||
|
||||
void tcp_mux_encode(enum tcp_mux_type type, enum tcp_mux_flag flags,
|
||||
uint32_t stream_id, uint32_t length, struct tcp_mux_header *tmux_hdr);
|
||||
|
||||
int handle_tcp_mux_stream(struct tcp_mux_header *tmux_hdr, handle_data_fn_t fn);
|
||||
|
||||
void handle_tcp_mux_ping(struct tcp_mux_header *tmux_hdr);
|
||||
|
||||
void handle_tcp_mux_go_away(struct tcp_mux_header *tmux_hdr);
|
||||
|
||||
uint32_t tmux_stream_write(struct bufferevent *bev, uint8_t *data, uint32_t length, struct tmux_stream *stream);
|
||||
|
||||
uint32_t tmux_stream_read(struct bufferevent *bev, struct tmux_stream *stream, uint32_t len);
|
||||
|
||||
void reset_session_id();
|
||||
|
||||
struct tmux_stream *get_cur_stream();
|
||||
|
||||
void set_cur_stream(struct tmux_stream *stream);
|
||||
|
||||
void add_stream(struct tmux_stream *stream);
|
||||
|
||||
void del_stream(uint32_t stream_id);
|
||||
|
||||
void clear_stream();
|
||||
|
||||
struct tmux_stream* get_stream_by_id(uint32_t id);
|
||||
|
||||
int tmux_stream_close(struct bufferevent *bout, struct tmux_stream *stream);
|
||||
|
||||
int rx_ring_buffer_pop(struct ring_buffer *ring, uint8_t *data, uint32_t len);
|
||||
|
||||
uint32_t rx_ring_buffer_read(struct bufferevent *bev, struct ring_buffer *ring, uint32_t len);
|
||||
|
||||
uint32_t tx_ring_buffer_write(struct bufferevent *bev, struct ring_buffer *ring, uint32_t len);
|
||||
|
||||
#endif
|
||||
164
thirdparty/CMakeLists.txt
vendored
Normal file
164
thirdparty/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
message(STATUS "PROJECT PATH IS: :${PROJECT_SOURCE_DIR}")
|
||||
message(STATUS "architecture is::${THIRDPARTY_STATIC_BUILD}")
|
||||
|
||||
if (THIRDPARTY_STATIC_BUILD STREQUAL "mips")
|
||||
set(ARCH_FLAG "linux-mips32")
|
||||
set(CROSS_C_COMPILER ${CMAKE_C_COMPILER})
|
||||
elseif (THIRDPARTY_STATIC_BUILD STREQUAL "arm")
|
||||
set(ARCH_FLAG "linux-armv4")
|
||||
set(CROSS_C_COMPILER ${CMAKE_C_COMPILER})
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
#openssl compile and add libs to libs file
|
||||
message(STATUS "compiling openssl")
|
||||
execute_process(
|
||||
COMMAND rm -rf ../libs
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/thirdparty/openssl-1.1.1m"
|
||||
)
|
||||
execute_process(
|
||||
COMMAND mkdir ../libs
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/thirdparty/openssl-1.1.1m"
|
||||
)
|
||||
|
||||
execute_process(
|
||||
COMMAND chmod +x config
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/thirdparty/openssl-1.1.1m"
|
||||
)
|
||||
|
||||
execute_process(
|
||||
COMMAND chmod +x Configure
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/thirdparty/openssl-1.1.1m"
|
||||
)
|
||||
|
||||
if (THIRDPARTY_STATIC_BUILD STREQUAL "ON")
|
||||
execute_process(
|
||||
COMMAND ./config --static
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/thirdparty/openssl-1.1.1m"
|
||||
)
|
||||
elseif (THIRDPARTY_STATIC_BUILD STREQUAL "mips" OR THIRDPARTY_STATIC_BUILD STREQUAL "arm")
|
||||
execute_process(
|
||||
COMMAND ./Configure ${ARCH_FLAG} --static
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/thirdparty/openssl-1.1.1m"
|
||||
)
|
||||
endif(THIRDPARTY_STATIC_BUILD)
|
||||
|
||||
execute_process(
|
||||
COMMAND make -j${NPROC}
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/thirdparty/openssl-1.1.1m"
|
||||
)
|
||||
|
||||
execute_process(
|
||||
COMMAND cp -f libcrypto.a ../libs
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/thirdparty/openssl-1.1.1m"
|
||||
)
|
||||
|
||||
execute_process(
|
||||
COMMAND cp -f libssl.a ../libs
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/thirdparty/openssl-1.1.1m"
|
||||
)
|
||||
|
||||
execute_process(
|
||||
COMMAND cp -rf include/openssl ../include
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/thirdparty/openssl-1.1.1m"
|
||||
)
|
||||
|
||||
#libevent compile and add libs to libs file
|
||||
message(STATUS "compiling libevnet")
|
||||
execute_process(
|
||||
COMMAND rm -rf build
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/thirdparty/libevent-2.1.10"
|
||||
)
|
||||
|
||||
execute_process(
|
||||
COMMAND mkdir build
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/thirdparty/libevent-2.1.10"
|
||||
)
|
||||
if (THIRDPARTY_STATIC_BUILD STREQUAL "ON")
|
||||
execute_process(
|
||||
COMMAND cmake -DOPENSSL_ROOT_DIR=${PROJECT_SOURCE_DIR}/thirdparty/openssl-1.1.1m -DOPENSSL_LIBRARES=${PROJECT_SOURCE_DIR}/thirdparty/openssl-1.1.1m ..
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/thirdparty/libevent-2.1.10/build"
|
||||
)
|
||||
else()
|
||||
execute_process(
|
||||
COMMAND cmake -DCMAKE_C_COMPILER=${CROSS_C_COMPILER} -DOPENSSL_ROOT_DIR=${PROJECT_SOURCE_DIR}/thirdparty/openssl-1.1.1m -DOPENSSL_LIBRARES=${PROJECT_SOURCE_DIR}/thirdparty/openssl-1.1.1m ..
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/thirdparty/libevent-2.1.10/build"
|
||||
)
|
||||
endif(THIRDPARTY_STATIC_BUILD)
|
||||
|
||||
execute_process(
|
||||
COMMAND make -j${NPROC}
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/thirdparty/libevent-2.1.10/build"
|
||||
)
|
||||
# wait libevent create libs
|
||||
set(EVENT_BUILD_PATH ${PROJECT_SOURCE_DIR}/thirdparty/libevent-2.1.10/build)
|
||||
set(LIBS_PATH ${PROJECT_SOURCE_DIR}/thirdparty/libs)
|
||||
|
||||
file(GLOB EVENT_LIBS_PATH
|
||||
"${EVENT_BUILD_PATH}/lib/libevent*.a"
|
||||
)
|
||||
file(COPY ${EVENT_LIBS_PATH} DESTINATION ${LIBS_PATH})
|
||||
|
||||
#json-c compile and add libs to libs file
|
||||
message(STATUS "compiling json-c")
|
||||
execute_process(
|
||||
COMMAND rm -rf build
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/thirdparty/json-c"
|
||||
)
|
||||
|
||||
execute_process(
|
||||
COMMAND mkdir build
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/thirdparty/json-c"
|
||||
)
|
||||
if (THIRDPARTY_STATIC_BUILD STREQUAL "ON")
|
||||
execute_process(
|
||||
COMMAND cmake ..
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/thirdparty/json-c/build"
|
||||
)
|
||||
else()
|
||||
execute_process(
|
||||
COMMAND cmake -DCMAKE_C_COMPILER=${CROSS_C_COMPILER} ..
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/thirdparty/json-c/build"
|
||||
)
|
||||
endif(THIRDPARTY_STATIC_BUILD)
|
||||
|
||||
execute_process(
|
||||
COMMAND make -j${NPROC}
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/thirdparty/json-c/build"
|
||||
)
|
||||
|
||||
|
||||
execute_process(
|
||||
COMMAND cp -f libjson-c.a ../../libs
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/thirdparty/json-c/build"
|
||||
)
|
||||
|
||||
execute_process(
|
||||
COMMAND cp -f json.h ../../include/json-c
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/thirdparty/json-c/build"
|
||||
)
|
||||
|
||||
# compile mips or arm
|
||||
if (THIRDPARTY_STATIC_BUILD STREQUAL "arm" OR THIRDPARTY_STATIC_BUILD STREQUAL "mips")
|
||||
execute_process(
|
||||
COMMAND chmod +x configure
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/thirdparty/zlib-1.2.13"
|
||||
)
|
||||
execute_process(
|
||||
COMMAND ./configure
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/thirdparty/zlib-1.2.13"
|
||||
)
|
||||
execute_process(
|
||||
COMMAND make -j${NPROC}
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/thirdparty/zlib-1.2.13"
|
||||
)
|
||||
execute_process(
|
||||
COMMAND cp -f libz.a ../libs
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/thirdparty/zlib-1.2.13"
|
||||
)
|
||||
endif(THIRDPARTY_STATIC_BUILD)
|
||||
|
||||
88
thirdparty/include/json-c/arraylist.h
vendored
Normal file
88
thirdparty/include/json-c/arraylist.h
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* $Id: arraylist.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
|
||||
*
|
||||
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
|
||||
* Michael Clark <michael@metaparadigm.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See COPYING for details.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Internal methods for working with json_type_array objects.
|
||||
* Although this is exposed by the json_object_get_array() method,
|
||||
* it is not recommended for direct use.
|
||||
*/
|
||||
#ifndef _arraylist_h_
|
||||
#define _arraylist_h_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#define ARRAY_LIST_DEFAULT_SIZE 32
|
||||
|
||||
typedef void(array_list_free_fn)(void *data);
|
||||
|
||||
struct array_list
|
||||
{
|
||||
void **array;
|
||||
size_t length;
|
||||
size_t size;
|
||||
array_list_free_fn *free_fn;
|
||||
};
|
||||
typedef struct array_list array_list;
|
||||
|
||||
/**
|
||||
* Allocate an array_list of the default size (32).
|
||||
* @deprecated Use array_list_new2() instead.
|
||||
*/
|
||||
extern struct array_list *array_list_new(array_list_free_fn *free_fn);
|
||||
|
||||
/**
|
||||
* Allocate an array_list of the desired size.
|
||||
*
|
||||
* If possible, the size should be chosen to closely match
|
||||
* the actual number of elements expected to be used.
|
||||
* If the exact size is unknown, there are tradeoffs to be made:
|
||||
* - too small - the array_list code will need to call realloc() more
|
||||
* often (which might incur an additional memory copy).
|
||||
* - too large - will waste memory, but that can be mitigated
|
||||
* by calling array_list_shrink() once the final size is known.
|
||||
*
|
||||
* @see array_list_shrink
|
||||
*/
|
||||
extern struct array_list *array_list_new2(array_list_free_fn *free_fn, int initial_size);
|
||||
|
||||
extern void array_list_free(struct array_list *al);
|
||||
|
||||
extern void *array_list_get_idx(struct array_list *al, size_t i);
|
||||
|
||||
extern int array_list_put_idx(struct array_list *al, size_t i, void *data);
|
||||
|
||||
extern int array_list_add(struct array_list *al, void *data);
|
||||
|
||||
extern size_t array_list_length(struct array_list *al);
|
||||
|
||||
extern void array_list_sort(struct array_list *arr, int (*compar)(const void *, const void *));
|
||||
|
||||
extern void *array_list_bsearch(const void **key, struct array_list *arr,
|
||||
int (*compar)(const void *, const void *));
|
||||
|
||||
extern int array_list_del_idx(struct array_list *arr, size_t idx, size_t count);
|
||||
|
||||
/**
|
||||
* Shrink the array list to just enough to fit the number of elements in it,
|
||||
* plus empty_slots.
|
||||
*/
|
||||
extern int array_list_shrink(struct array_list *arr, size_t empty_slots);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
98
thirdparty/include/json-c/debug.h
vendored
Normal file
98
thirdparty/include/json-c/debug.h
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* $Id: debug.h,v 1.5 2006/01/30 23:07:57 mclark Exp $
|
||||
*
|
||||
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
|
||||
* Michael Clark <michael@metaparadigm.com>
|
||||
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See COPYING for details.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Do not use, json-c internal, may be changed or removed at any time.
|
||||
*/
|
||||
#ifndef _DEBUG_H_
|
||||
#define _DEBUG_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef JSON_EXPORT
|
||||
#if defined(_MSC_VER)
|
||||
#define JSON_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define JSON_EXPORT extern
|
||||
#endif
|
||||
#endif
|
||||
|
||||
JSON_EXPORT void mc_set_debug(int debug);
|
||||
JSON_EXPORT int mc_get_debug(void);
|
||||
|
||||
JSON_EXPORT void mc_set_syslog(int syslog);
|
||||
|
||||
JSON_EXPORT void mc_debug(const char *msg, ...);
|
||||
JSON_EXPORT void mc_error(const char *msg, ...);
|
||||
JSON_EXPORT void mc_info(const char *msg, ...);
|
||||
|
||||
#ifndef __STRING
|
||||
#define __STRING(x) #x
|
||||
#endif
|
||||
|
||||
#ifndef PARSER_BROKEN_FIXED
|
||||
|
||||
#define JASSERT(cond) \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define JASSERT(cond) \
|
||||
do \
|
||||
{ \
|
||||
if (!(cond)) \
|
||||
{ \
|
||||
mc_error("cjson assert failure %s:%d : cond \"" __STRING(cond) "failed\n", \
|
||||
__FILE__, __LINE__); \
|
||||
*(int *)0 = 1; \
|
||||
abort(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
#define MC_ERROR(x, ...) mc_error(x, ##__VA_ARGS__)
|
||||
|
||||
#ifdef MC_MAINTAINER_MODE
|
||||
#define MC_SET_DEBUG(x) mc_set_debug(x)
|
||||
#define MC_GET_DEBUG() mc_get_debug()
|
||||
#define MC_SET_SYSLOG(x) mc_set_syslog(x)
|
||||
#define MC_DEBUG(x, ...) mc_debug(x, ##__VA_ARGS__)
|
||||
#define MC_INFO(x, ...) mc_info(x, ##__VA_ARGS__)
|
||||
#else
|
||||
#define MC_SET_DEBUG(x) \
|
||||
if (0) \
|
||||
mc_set_debug(x)
|
||||
#define MC_GET_DEBUG() (0)
|
||||
#define MC_SET_SYSLOG(x) \
|
||||
if (0) \
|
||||
mc_set_syslog(x)
|
||||
#define MC_DEBUG(x, ...) \
|
||||
if (0) \
|
||||
mc_debug(x, ##__VA_ARGS__)
|
||||
#define MC_INFO(x, ...) \
|
||||
if (0) \
|
||||
mc_info(x, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
38
thirdparty/include/json-c/json.h
vendored
Normal file
38
thirdparty/include/json-c/json.h
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* $Id: json.h,v 1.6 2006/01/26 02:16:28 mclark Exp $
|
||||
*
|
||||
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
|
||||
* Michael Clark <michael@metaparadigm.com>
|
||||
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See COPYING for details.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief A convenience header that may be included instead of other individual ones.
|
||||
*/
|
||||
#ifndef _json_h_
|
||||
#define _json_h_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "arraylist.h"
|
||||
#include "debug.h"
|
||||
#include "json_c_version.h"
|
||||
#include "json_object.h"
|
||||
#include "json_object_iterator.h"
|
||||
#include "json_pointer.h"
|
||||
#include "json_tokener.h"
|
||||
#include "json_util.h"
|
||||
#include "linkhash.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
55
thirdparty/include/json-c/json_c_version.h
vendored
Normal file
55
thirdparty/include/json-c/json_c_version.h
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2012,2017,2019,2020 Eric Hawicz
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See COPYING for details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Methods for retrieving the json-c version.
|
||||
*/
|
||||
#ifndef _json_c_version_h_
|
||||
#define _json_c_version_h_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define JSON_C_MAJOR_VERSION 0
|
||||
#define JSON_C_MINOR_VERSION 15
|
||||
#define JSON_C_MICRO_VERSION 0
|
||||
#define JSON_C_VERSION_NUM \
|
||||
((JSON_C_MAJOR_VERSION << 16) | (JSON_C_MINOR_VERSION << 8) | JSON_C_MICRO_VERSION)
|
||||
#define JSON_C_VERSION "0.15"
|
||||
|
||||
#ifndef JSON_EXPORT
|
||||
#if defined(_MSC_VER)
|
||||
#define JSON_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define JSON_EXPORT extern
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @see JSON_C_VERSION
|
||||
* @return the version of the json-c library as a string
|
||||
*/
|
||||
JSON_EXPORT const char *json_c_version(void); /* Returns JSON_C_VERSION */
|
||||
|
||||
/**
|
||||
* The json-c version encoded into an int, with the low order 8 bits
|
||||
* being the micro version, the next higher 8 bits being the minor version
|
||||
* and the next higher 8 bits being the major version.
|
||||
* For example, 7.12.99 would be 0x00070B63.
|
||||
*
|
||||
* @see JSON_C_VERSION_NUM
|
||||
* @return the version of the json-c library as an int
|
||||
*/
|
||||
JSON_EXPORT int json_c_version_num(void); /* Returns JSON_C_VERSION_NUM */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
2
thirdparty/include/json-c/json_config.h
vendored
Normal file
2
thirdparty/include/json-c/json_config.h
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define JSON_C_HAVE_INTTYPES_H 1
|
||||
24
thirdparty/include/json-c/json_inttypes.h
vendored
Normal file
24
thirdparty/include/json-c/json_inttypes.h
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Do not use, json-c internal, may be changed or removed at any time.
|
||||
*/
|
||||
#ifndef _json_inttypes_h_
|
||||
#define _json_inttypes_h_
|
||||
|
||||
#include "json_config.h"
|
||||
|
||||
#ifdef JSON_C_HAVE_INTTYPES_H
|
||||
/* inttypes.h includes stdint.h */
|
||||
#include <inttypes.h>
|
||||
|
||||
#else
|
||||
#include <stdint.h>
|
||||
|
||||
#define PRId64 "I64d"
|
||||
#define SCNd64 "I64d"
|
||||
#define PRIu64 "I64u"
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
1068
thirdparty/include/json-c/json_object.h
vendored
Normal file
1068
thirdparty/include/json-c/json_object.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
228
thirdparty/include/json-c/json_object_iterator.h
vendored
Normal file
228
thirdparty/include/json-c/json_object_iterator.h
vendored
Normal file
@@ -0,0 +1,228 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file json_object_iterator.h
|
||||
*
|
||||
* Copyright (c) 2009-2012 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See COPYING for details.
|
||||
*
|
||||
* @brief An API for iterating over json_type_object objects,
|
||||
* styled to be familiar to C++ programmers.
|
||||
* Unlike json_object_object_foreach() and
|
||||
* json_object_object_foreachC(), this avoids the need to expose
|
||||
* json-c internals like lh_entry.
|
||||
*
|
||||
* API attributes: <br>
|
||||
* * Thread-safe: NO<br>
|
||||
* * Reentrant: NO
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef JSON_OBJECT_ITERATOR_H
|
||||
#define JSON_OBJECT_ITERATOR_H
|
||||
|
||||
#include "json_types.h"
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Forward declaration for the opaque iterator information.
|
||||
*/
|
||||
struct json_object_iter_info_;
|
||||
|
||||
/**
|
||||
* The opaque iterator that references a name/value pair within
|
||||
* a JSON Object instance or the "end" iterator value.
|
||||
*/
|
||||
struct json_object_iterator
|
||||
{
|
||||
const void *opaque_;
|
||||
};
|
||||
|
||||
/**
|
||||
* forward declaration of json-c's JSON value instance structure
|
||||
*/
|
||||
struct json_object;
|
||||
|
||||
/**
|
||||
* Initializes an iterator structure to a "default" value that
|
||||
* is convenient for initializing an iterator variable to a
|
||||
* default state (e.g., initialization list in a class'
|
||||
* constructor).
|
||||
*
|
||||
* @code
|
||||
* struct json_object_iterator iter = json_object_iter_init_default();
|
||||
* MyClass() : iter_(json_object_iter_init_default())
|
||||
* @endcode
|
||||
*
|
||||
* @note The initialized value doesn't reference any specific
|
||||
* pair, is considered an invalid iterator, and MUST NOT
|
||||
* be passed to any json-c API that expects a valid
|
||||
* iterator.
|
||||
*
|
||||
* @note User and internal code MUST NOT make any assumptions
|
||||
* about and dependencies on the value of the "default"
|
||||
* iterator value.
|
||||
*
|
||||
* @return json_object_iterator
|
||||
*/
|
||||
JSON_EXPORT struct json_object_iterator json_object_iter_init_default(void);
|
||||
|
||||
/** Retrieves an iterator to the first pair of the JSON Object.
|
||||
*
|
||||
* @warning Any modification of the underlying pair invalidates all
|
||||
* iterators to that pair.
|
||||
*
|
||||
* @param obj JSON Object instance (MUST be of type json_object)
|
||||
*
|
||||
* @return json_object_iterator If the JSON Object has at
|
||||
* least one pair, on return, the iterator refers
|
||||
* to the first pair. If the JSON Object doesn't
|
||||
* have any pairs, the returned iterator is
|
||||
* equivalent to the "end" iterator for the same
|
||||
* JSON Object instance.
|
||||
*
|
||||
* @code
|
||||
* struct json_object_iterator it;
|
||||
* struct json_object_iterator itEnd;
|
||||
* struct json_object* obj;
|
||||
*
|
||||
* obj = json_tokener_parse("{'first':'george', 'age':100}");
|
||||
* it = json_object_iter_begin(obj);
|
||||
* itEnd = json_object_iter_end(obj);
|
||||
*
|
||||
* while (!json_object_iter_equal(&it, &itEnd)) {
|
||||
* printf("%s\n",
|
||||
* json_object_iter_peek_name(&it));
|
||||
* json_object_iter_next(&it);
|
||||
* }
|
||||
*
|
||||
* @endcode
|
||||
*/
|
||||
JSON_EXPORT struct json_object_iterator json_object_iter_begin(struct json_object *obj);
|
||||
|
||||
/** Retrieves the iterator that represents the position beyond the
|
||||
* last pair of the given JSON Object instance.
|
||||
*
|
||||
* @warning Do NOT write code that assumes that the "end"
|
||||
* iterator value is NULL, even if it is so in a
|
||||
* particular instance of the implementation.
|
||||
*
|
||||
* @note The reason we do not (and MUST NOT) provide
|
||||
* "json_object_iter_is_end(json_object_iterator* iter)"
|
||||
* type of API is because it would limit the underlying
|
||||
* representation of name/value containment (or force us
|
||||
* to add additional, otherwise unnecessary, fields to
|
||||
* the iterator structure). The "end" iterator and the
|
||||
* equality test method, on the other hand, permit us to
|
||||
* cleanly abstract pretty much any reasonable underlying
|
||||
* representation without burdening the iterator
|
||||
* structure with unnecessary data.
|
||||
*
|
||||
* @note For performance reasons, memorize the "end" iterator prior
|
||||
* to any loop.
|
||||
*
|
||||
* @param obj JSON Object instance (MUST be of type json_object)
|
||||
*
|
||||
* @return json_object_iterator On return, the iterator refers
|
||||
* to the "end" of the Object instance's pairs
|
||||
* (i.e., NOT the last pair, but "beyond the last
|
||||
* pair" value)
|
||||
*/
|
||||
JSON_EXPORT struct json_object_iterator json_object_iter_end(const struct json_object *obj);
|
||||
|
||||
/** Returns an iterator to the next pair, if any
|
||||
*
|
||||
* @warning Any modification of the underlying pair
|
||||
* invalidates all iterators to that pair.
|
||||
*
|
||||
* @param iter [IN/OUT] Pointer to iterator that references a
|
||||
* name/value pair; MUST be a valid, non-end iterator.
|
||||
* WARNING: bad things will happen if invalid or "end"
|
||||
* iterator is passed. Upon return will contain the
|
||||
* reference to the next pair if there is one; if there
|
||||
* are no more pairs, will contain the "end" iterator
|
||||
* value, which may be compared against the return value
|
||||
* of json_object_iter_end() for the same JSON Object
|
||||
* instance.
|
||||
*/
|
||||
JSON_EXPORT void json_object_iter_next(struct json_object_iterator *iter);
|
||||
|
||||
/** Returns a const pointer to the name of the pair referenced
|
||||
* by the given iterator.
|
||||
*
|
||||
* @param iter pointer to iterator that references a name/value
|
||||
* pair; MUST be a valid, non-end iterator.
|
||||
*
|
||||
* @warning bad things will happen if an invalid or
|
||||
* "end" iterator is passed.
|
||||
*
|
||||
* @return const char* Pointer to the name of the referenced
|
||||
* name/value pair. The name memory belongs to the
|
||||
* name/value pair, will be freed when the pair is
|
||||
* deleted or modified, and MUST NOT be modified or
|
||||
* freed by the user.
|
||||
*/
|
||||
JSON_EXPORT const char *json_object_iter_peek_name(const struct json_object_iterator *iter);
|
||||
|
||||
/** Returns a pointer to the json-c instance representing the
|
||||
* value of the referenced name/value pair, without altering
|
||||
* the instance's reference count.
|
||||
*
|
||||
* @param iter pointer to iterator that references a name/value
|
||||
* pair; MUST be a valid, non-end iterator.
|
||||
*
|
||||
* @warning bad things will happen if invalid or
|
||||
* "end" iterator is passed.
|
||||
*
|
||||
* @return struct json_object* Pointer to the json-c value
|
||||
* instance of the referenced name/value pair; the
|
||||
* value's reference count is not changed by this
|
||||
* function: if you plan to hold on to this json-c node,
|
||||
* take a look at json_object_get() and
|
||||
* json_object_put(). IMPORTANT: json-c API represents
|
||||
* the JSON Null value as a NULL json_object instance
|
||||
* pointer.
|
||||
*/
|
||||
JSON_EXPORT struct json_object *
|
||||
json_object_iter_peek_value(const struct json_object_iterator *iter);
|
||||
|
||||
/** Tests two iterators for equality. Typically used to test
|
||||
* for end of iteration by comparing an iterator to the
|
||||
* corresponding "end" iterator (that was derived from the same
|
||||
* JSON Object instance).
|
||||
*
|
||||
* @note The reason we do not (and MUST NOT) provide
|
||||
* "json_object_iter_is_end(json_object_iterator* iter)"
|
||||
* type of API is because it would limit the underlying
|
||||
* representation of name/value containment (or force us
|
||||
* to add additional, otherwise unnecessary, fields to
|
||||
* the iterator structure). The equality test method, on
|
||||
* the other hand, permits us to cleanly abstract pretty
|
||||
* much any reasonable underlying representation.
|
||||
*
|
||||
* @param iter1 Pointer to first valid, non-NULL iterator
|
||||
* @param iter2 POinter to second valid, non-NULL iterator
|
||||
*
|
||||
* @warning if a NULL iterator pointer or an uninitialized
|
||||
* or invalid iterator, or iterators derived from
|
||||
* different JSON Object instances are passed, bad things
|
||||
* will happen!
|
||||
*
|
||||
* @return json_bool non-zero if iterators are equal (i.e., both
|
||||
* reference the same name/value pair or are both at
|
||||
* "end"); zero if they are not equal.
|
||||
*/
|
||||
JSON_EXPORT json_bool json_object_iter_equal(const struct json_object_iterator *iter1,
|
||||
const struct json_object_iterator *iter2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* JSON_OBJECT_ITERATOR_H */
|
||||
123
thirdparty/include/json-c/json_pointer.h
vendored
Normal file
123
thirdparty/include/json-c/json_pointer.h
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Alexadru Ardelean.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See COPYING for details.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief JSON Pointer (RFC 6901) implementation for retrieving
|
||||
* objects from a json-c object tree.
|
||||
*/
|
||||
#ifndef _json_pointer_h_
|
||||
#define _json_pointer_h_
|
||||
|
||||
#include "json_object.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Retrieves a JSON sub-object from inside another JSON object
|
||||
* using the JSON pointer notation as defined in RFC 6901
|
||||
* https://tools.ietf.org/html/rfc6901
|
||||
*
|
||||
* The returned JSON sub-object is equivalent to parsing manually the
|
||||
* 'obj' JSON tree ; i.e. it's not a new object that is created, but rather
|
||||
* a pointer inside the JSON tree.
|
||||
*
|
||||
* Internally, this is equivalent to doing a series of 'json_object_object_get()'
|
||||
* and 'json_object_array_get_idx()' along the given 'path'.
|
||||
*
|
||||
* Note that the 'path' string supports 'printf()' type arguments, so, whatever
|
||||
* is added after the 'res' param will be treated as an argument for 'path'
|
||||
* Example: json_pointer_get(obj, "/foo/%d/%s", &res, 0, bar)
|
||||
* This means, that you need to escape '%' with '%%' (just like in printf())
|
||||
*
|
||||
* @param obj the json_object instance/tree from where to retrieve sub-objects
|
||||
* @param path a (RFC6901) string notation for the sub-object to retrieve
|
||||
* @param res a pointer that stores a reference to the json_object
|
||||
* associated with the given path
|
||||
*
|
||||
* @return negative if an error (or not found), or 0 if succeeded
|
||||
*/
|
||||
JSON_EXPORT int json_pointer_get(struct json_object *obj, const char *path,
|
||||
struct json_object **res);
|
||||
|
||||
/**
|
||||
* This is a variant of 'json_pointer_get()' that supports printf() style arguments.
|
||||
*
|
||||
* Example: json_pointer_getf(obj, res, "/foo/%d/%s", 0, bak)
|
||||
* This also means that you need to escape '%' with '%%' (just like in printf())
|
||||
*
|
||||
* Please take into consideration all recommended 'printf()' format security
|
||||
* aspects when using this function.
|
||||
*
|
||||
* @param obj the json_object instance/tree to which to add a sub-object
|
||||
* @param res a pointer that stores a reference to the json_object
|
||||
* associated with the given path
|
||||
* @param path_fmt a printf() style format for the path
|
||||
*
|
||||
* @return negative if an error (or not found), or 0 if succeeded
|
||||
*/
|
||||
JSON_EXPORT int json_pointer_getf(struct json_object *obj, struct json_object **res,
|
||||
const char *path_fmt, ...);
|
||||
|
||||
/**
|
||||
* Sets JSON object 'value' in the 'obj' tree at the location specified
|
||||
* by the 'path'. 'path' is JSON pointer notation as defined in RFC 6901
|
||||
* https://tools.ietf.org/html/rfc6901
|
||||
*
|
||||
* Note that 'obj' is a double pointer, mostly for the "" (empty string)
|
||||
* case, where the entire JSON object would be replaced by 'value'.
|
||||
* In the case of the "" path, the object at '*obj' will have it's refcount
|
||||
* decremented with 'json_object_put()' and the 'value' object will be assigned to it.
|
||||
*
|
||||
* For other cases (JSON sub-objects) ownership of 'value' will be transferred into
|
||||
* '*obj' via 'json_object_object_add()' & 'json_object_array_put_idx()', so the
|
||||
* only time the refcount should be decremented for 'value' is when the return value of
|
||||
* 'json_pointer_set()' is negative (meaning the 'value' object did not get set into '*obj').
|
||||
*
|
||||
* That also implies that 'json_pointer_set()' does not do any refcount incrementing.
|
||||
* (Just that single decrement that was mentioned above).
|
||||
*
|
||||
* Note that the 'path' string supports 'printf()' type arguments, so, whatever
|
||||
* is added after the 'value' param will be treated as an argument for 'path'
|
||||
* Example: json_pointer_set(obj, "/foo/%d/%s", value, 0, bak)
|
||||
* This means, that you need to escape '%' with '%%' (just like in printf())
|
||||
*
|
||||
* @param obj the json_object instance/tree to which to add a sub-object
|
||||
* @param path a (RFC6901) string notation for the sub-object to set in the tree
|
||||
* @param value object to set at path
|
||||
*
|
||||
* @return negative if an error (or not found), or 0 if succeeded
|
||||
*/
|
||||
JSON_EXPORT int json_pointer_set(struct json_object **obj, const char *path,
|
||||
struct json_object *value);
|
||||
|
||||
/**
|
||||
* This is a variant of 'json_pointer_set()' that supports printf() style arguments.
|
||||
*
|
||||
* Example: json_pointer_setf(obj, value, "/foo/%d/%s", 0, bak)
|
||||
* This also means that you need to escape '%' with '%%' (just like in printf())
|
||||
*
|
||||
* Please take into consideration all recommended 'printf()' format security
|
||||
* aspects when using this function.
|
||||
*
|
||||
* @param obj the json_object instance/tree to which to add a sub-object
|
||||
* @param value object to set at path
|
||||
* @param path_fmt a printf() style format for the path
|
||||
*
|
||||
* @return negative if an error (or not found), or 0 if succeeded
|
||||
*/
|
||||
JSON_EXPORT int json_pointer_setf(struct json_object **obj, struct json_object *value,
|
||||
const char *path_fmt, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
328
thirdparty/include/json-c/json_tokener.h
vendored
Normal file
328
thirdparty/include/json-c/json_tokener.h
vendored
Normal file
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* $Id: json_tokener.h,v 1.10 2006/07/25 03:24:50 mclark Exp $
|
||||
*
|
||||
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
|
||||
* Michael Clark <michael@metaparadigm.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See COPYING for details.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Methods to parse an input string into a tree of json_object objects.
|
||||
*/
|
||||
#ifndef _json_tokener_h_
|
||||
#define _json_tokener_h_
|
||||
|
||||
#include "json_object.h"
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum json_tokener_error
|
||||
{
|
||||
json_tokener_success,
|
||||
json_tokener_continue,
|
||||
json_tokener_error_depth,
|
||||
json_tokener_error_parse_eof,
|
||||
json_tokener_error_parse_unexpected,
|
||||
json_tokener_error_parse_null,
|
||||
json_tokener_error_parse_boolean,
|
||||
json_tokener_error_parse_number,
|
||||
json_tokener_error_parse_array,
|
||||
json_tokener_error_parse_object_key_name,
|
||||
json_tokener_error_parse_object_key_sep,
|
||||
json_tokener_error_parse_object_value_sep,
|
||||
json_tokener_error_parse_string,
|
||||
json_tokener_error_parse_comment,
|
||||
json_tokener_error_parse_utf8_string,
|
||||
json_tokener_error_size
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated Don't use this outside of json_tokener.c, it will be made private in a future release.
|
||||
*/
|
||||
enum json_tokener_state
|
||||
{
|
||||
json_tokener_state_eatws,
|
||||
json_tokener_state_start,
|
||||
json_tokener_state_finish,
|
||||
json_tokener_state_null,
|
||||
json_tokener_state_comment_start,
|
||||
json_tokener_state_comment,
|
||||
json_tokener_state_comment_eol,
|
||||
json_tokener_state_comment_end,
|
||||
json_tokener_state_string,
|
||||
json_tokener_state_string_escape,
|
||||
json_tokener_state_escape_unicode,
|
||||
json_tokener_state_escape_unicode_need_escape,
|
||||
json_tokener_state_escape_unicode_need_u,
|
||||
json_tokener_state_boolean,
|
||||
json_tokener_state_number,
|
||||
json_tokener_state_array,
|
||||
json_tokener_state_array_add,
|
||||
json_tokener_state_array_sep,
|
||||
json_tokener_state_object_field_start,
|
||||
json_tokener_state_object_field,
|
||||
json_tokener_state_object_field_end,
|
||||
json_tokener_state_object_value,
|
||||
json_tokener_state_object_value_add,
|
||||
json_tokener_state_object_sep,
|
||||
json_tokener_state_array_after_sep,
|
||||
json_tokener_state_object_field_start_after_sep,
|
||||
json_tokener_state_inf
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated Don't use this outside of json_tokener.c, it will be made private in a future release.
|
||||
*/
|
||||
struct json_tokener_srec
|
||||
{
|
||||
enum json_tokener_state state, saved_state;
|
||||
struct json_object *obj;
|
||||
struct json_object *current;
|
||||
char *obj_field_name;
|
||||
};
|
||||
|
||||
#define JSON_TOKENER_DEFAULT_DEPTH 32
|
||||
|
||||
/**
|
||||
* Internal state of the json parser.
|
||||
* Do not access any fields of this structure directly.
|
||||
* Its definition is published due to historical limitations
|
||||
* in the json tokener API, and will be changed to be an opaque
|
||||
* type in the future.
|
||||
*/
|
||||
struct json_tokener
|
||||
{
|
||||
/**
|
||||
* @deprecated Do not access any of these fields outside of json_tokener.c
|
||||
*/
|
||||
char *str;
|
||||
struct printbuf *pb;
|
||||
int max_depth, depth, is_double, st_pos;
|
||||
/**
|
||||
* @deprecated See json_tokener_get_parse_end() instead.
|
||||
*/
|
||||
int char_offset;
|
||||
/**
|
||||
* @deprecated See json_tokener_get_error() instead.
|
||||
*/
|
||||
enum json_tokener_error err;
|
||||
unsigned int ucs_char, high_surrogate;
|
||||
char quote_char;
|
||||
struct json_tokener_srec *stack;
|
||||
int flags;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the offset of the byte after the last byte parsed
|
||||
* relative to the start of the most recent string passed in
|
||||
* to json_tokener_parse_ex(). i.e. this is where parsing
|
||||
* would start again if the input contains another JSON object
|
||||
* after the currently parsed one.
|
||||
*
|
||||
* Note that when multiple parse calls are issued, this is *not* the
|
||||
* total number of characters parsed.
|
||||
*
|
||||
* In the past this would have been accessed as tok->char_offset.
|
||||
*
|
||||
* See json_tokener_parse_ex() for an example of how to use this.
|
||||
*/
|
||||
JSON_EXPORT size_t json_tokener_get_parse_end(struct json_tokener *tok);
|
||||
|
||||
/**
|
||||
* @deprecated Unused in json-c code
|
||||
*/
|
||||
typedef struct json_tokener json_tokener;
|
||||
|
||||
/**
|
||||
* Be strict when parsing JSON input. Use caution with
|
||||
* this flag as what is considered valid may become more
|
||||
* restrictive from one release to the next, causing your
|
||||
* code to fail on previously working input.
|
||||
*
|
||||
* Note that setting this will also effectively disable parsing
|
||||
* of multiple json objects in a single character stream
|
||||
* (e.g. {"foo":123}{"bar":234}); if you want to allow that
|
||||
* also set JSON_TOKENER_ALLOW_TRAILING_CHARS
|
||||
*
|
||||
* This flag is not set by default.
|
||||
*
|
||||
* @see json_tokener_set_flags()
|
||||
*/
|
||||
#define JSON_TOKENER_STRICT 0x01
|
||||
|
||||
/**
|
||||
* Use with JSON_TOKENER_STRICT to allow trailing characters after the
|
||||
* first parsed object.
|
||||
*
|
||||
* @see json_tokener_set_flags()
|
||||
*/
|
||||
#define JSON_TOKENER_ALLOW_TRAILING_CHARS 0x02
|
||||
|
||||
/**
|
||||
* Cause json_tokener_parse_ex() to validate that input is UTF8.
|
||||
* If this flag is specified and validation fails, then
|
||||
* json_tokener_get_error(tok) will return
|
||||
* json_tokener_error_parse_utf8_string
|
||||
*
|
||||
* This flag is not set by default.
|
||||
*
|
||||
* @see json_tokener_set_flags()
|
||||
*/
|
||||
#define JSON_TOKENER_VALIDATE_UTF8 0x10
|
||||
|
||||
/**
|
||||
* Given an error previously returned by json_tokener_get_error(),
|
||||
* return a human readable description of the error.
|
||||
*
|
||||
* @return a generic error message is returned if an invalid error value is provided.
|
||||
*/
|
||||
JSON_EXPORT const char *json_tokener_error_desc(enum json_tokener_error jerr);
|
||||
|
||||
/**
|
||||
* Retrieve the error caused by the last call to json_tokener_parse_ex(),
|
||||
* or json_tokener_success if there is no error.
|
||||
*
|
||||
* When parsing a JSON string in pieces, if the tokener is in the middle
|
||||
* of parsing this will return json_tokener_continue.
|
||||
*
|
||||
* @see json_tokener_error_desc().
|
||||
*/
|
||||
JSON_EXPORT enum json_tokener_error json_tokener_get_error(struct json_tokener *tok);
|
||||
|
||||
/**
|
||||
* Allocate a new json_tokener.
|
||||
* When done using that to parse objects, free it with json_tokener_free().
|
||||
* See json_tokener_parse_ex() for usage details.
|
||||
*/
|
||||
JSON_EXPORT struct json_tokener *json_tokener_new(void);
|
||||
|
||||
/**
|
||||
* Allocate a new json_tokener with a custom max nesting depth.
|
||||
* @see JSON_TOKENER_DEFAULT_DEPTH
|
||||
*/
|
||||
JSON_EXPORT struct json_tokener *json_tokener_new_ex(int depth);
|
||||
|
||||
/**
|
||||
* Free a json_tokener previously allocated with json_tokener_new().
|
||||
*/
|
||||
JSON_EXPORT void json_tokener_free(struct json_tokener *tok);
|
||||
|
||||
/**
|
||||
* Reset the state of a json_tokener, to prepare to parse a
|
||||
* brand new JSON object.
|
||||
*/
|
||||
JSON_EXPORT void json_tokener_reset(struct json_tokener *tok);
|
||||
|
||||
/**
|
||||
* Parse a json_object out of the string `str`.
|
||||
*
|
||||
* If you need more control over how the parsing occurs,
|
||||
* see json_tokener_parse_ex().
|
||||
*/
|
||||
JSON_EXPORT struct json_object *json_tokener_parse(const char *str);
|
||||
|
||||
/**
|
||||
* Parser a json_object out of the string `str`, but if it fails
|
||||
* return the error in `*error`.
|
||||
* @see json_tokener_parse()
|
||||
* @see json_tokener_parse_ex()
|
||||
*/
|
||||
JSON_EXPORT struct json_object *json_tokener_parse_verbose(const char *str,
|
||||
enum json_tokener_error *error);
|
||||
|
||||
/**
|
||||
* Set flags that control how parsing will be done.
|
||||
*/
|
||||
JSON_EXPORT void json_tokener_set_flags(struct json_tokener *tok, int flags);
|
||||
|
||||
/**
|
||||
* Parse a string and return a non-NULL json_object if a valid JSON value
|
||||
* is found. The string does not need to be a JSON object or array;
|
||||
* it can also be a string, number or boolean value.
|
||||
*
|
||||
* A partial JSON string can be parsed. If the parsing is incomplete,
|
||||
* NULL will be returned and json_tokener_get_error() will return
|
||||
* json_tokener_continue.
|
||||
* json_tokener_parse_ex() can then be called with additional bytes in str
|
||||
* to continue the parsing.
|
||||
*
|
||||
* If json_tokener_parse_ex() returns NULL and the error is anything other than
|
||||
* json_tokener_continue, a fatal error has occurred and parsing must be
|
||||
* halted. Then, the tok object must not be reused until json_tokener_reset()
|
||||
* is called.
|
||||
*
|
||||
* When a valid JSON value is parsed, a non-NULL json_object will be
|
||||
* returned, with a reference count of one which belongs to the caller. Also,
|
||||
* json_tokener_get_error() will return json_tokener_success. Be sure to check
|
||||
* the type with json_object_is_type() or json_object_get_type() before using
|
||||
* the object.
|
||||
*
|
||||
* Trailing characters after the parsed value do not automatically cause an
|
||||
* error. It is up to the caller to decide whether to treat this as an
|
||||
* error or to handle the additional characters, perhaps by parsing another
|
||||
* json value starting from that point.
|
||||
*
|
||||
* If the caller knows that they are at the end of their input, the length
|
||||
* passed MUST include the final '\0' character, so values with no inherent
|
||||
* end (i.e. numbers) can be properly parsed, rather than just returning
|
||||
* json_tokener_continue.
|
||||
*
|
||||
* Extra characters can be detected by comparing the value returned by
|
||||
* json_tokener_get_parse_end() against
|
||||
* the length of the last len parameter passed in.
|
||||
*
|
||||
* The tokener does \b not maintain an internal buffer so the caller is
|
||||
* responsible for a subsequent call to json_tokener_parse_ex with an
|
||||
* appropriate str parameter starting with the extra characters.
|
||||
*
|
||||
* This interface is presently not 64-bit clean due to the int len argument
|
||||
* so the function limits the maximum string size to INT32_MAX (2GB).
|
||||
* If the function is called with len == -1 then strlen is called to check
|
||||
* the string length is less than INT32_MAX (2GB)
|
||||
*
|
||||
* Example:
|
||||
* @code
|
||||
json_object *jobj = NULL;
|
||||
const char *mystring = NULL;
|
||||
int stringlen = 0;
|
||||
enum json_tokener_error jerr;
|
||||
do {
|
||||
mystring = ... // get JSON string, e.g. read from file, etc...
|
||||
stringlen = strlen(mystring);
|
||||
if (end_of_input)
|
||||
stringlen++; // Include the '\0' if we know we're at the end of input
|
||||
jobj = json_tokener_parse_ex(tok, mystring, stringlen);
|
||||
} while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue);
|
||||
if (jerr != json_tokener_success)
|
||||
{
|
||||
fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr));
|
||||
// Handle errors, as appropriate for your application.
|
||||
}
|
||||
if (json_tokener_get_parse_end(tok) < stringlen)
|
||||
{
|
||||
// Handle extra characters after parsed object as desired.
|
||||
// e.g. issue an error, parse another object from that point, etc...
|
||||
}
|
||||
// Success, use jobj here.
|
||||
|
||||
@endcode
|
||||
*
|
||||
* @param tok a json_tokener previously allocated with json_tokener_new()
|
||||
* @param str an string with any valid JSON expression, or portion of. This does not need to be null terminated.
|
||||
* @param len the length of str
|
||||
*/
|
||||
JSON_EXPORT struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *str,
|
||||
int len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
78
thirdparty/include/json-c/json_types.h
vendored
Normal file
78
thirdparty/include/json-c/json_types.h
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Eric Hawicz
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See COPYING for details.
|
||||
*/
|
||||
|
||||
#ifndef _json_types_h_
|
||||
#define _json_types_h_
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Basic types used in a few places in json-c, but you should include "json_object.h" instead.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef JSON_EXPORT
|
||||
#if defined(_MSC_VER)
|
||||
#define JSON_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define JSON_EXPORT extern
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct printbuf;
|
||||
|
||||
/**
|
||||
* A structure to use with json_object_object_foreachC() loops.
|
||||
* Contains key, val and entry members.
|
||||
*/
|
||||
struct json_object_iter
|
||||
{
|
||||
char *key;
|
||||
struct json_object *val;
|
||||
struct lh_entry *entry;
|
||||
};
|
||||
typedef struct json_object_iter json_object_iter;
|
||||
|
||||
typedef int json_bool;
|
||||
|
||||
/**
|
||||
* @brief The core type for all type of JSON objects handled by json-c
|
||||
*/
|
||||
typedef struct json_object json_object;
|
||||
|
||||
/**
|
||||
* Type of custom user delete functions. See json_object_set_serializer.
|
||||
*/
|
||||
typedef void(json_object_delete_fn)(struct json_object *jso, void *userdata);
|
||||
|
||||
/**
|
||||
* Type of a custom serialization function. See json_object_set_serializer.
|
||||
*/
|
||||
typedef int(json_object_to_json_string_fn)(struct json_object *jso, struct printbuf *pb, int level,
|
||||
int flags);
|
||||
|
||||
/* supported object types */
|
||||
|
||||
typedef enum json_type
|
||||
{
|
||||
/* If you change this, be sure to update json_type_to_name() too */
|
||||
json_type_null,
|
||||
json_type_boolean,
|
||||
json_type_double,
|
||||
json_type_int,
|
||||
json_type_object,
|
||||
json_type_array,
|
||||
json_type_string
|
||||
} json_type;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
121
thirdparty/include/json-c/json_util.h
vendored
Normal file
121
thirdparty/include/json-c/json_util.h
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* $Id: json_util.h,v 1.4 2006/01/30 23:07:57 mclark Exp $
|
||||
*
|
||||
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
|
||||
* Michael Clark <michael@metaparadigm.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See COPYING for details.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Miscllaneous utility functions and macros.
|
||||
*/
|
||||
#ifndef _json_util_h_
|
||||
#define _json_util_h_
|
||||
|
||||
#include "json_object.h"
|
||||
|
||||
#ifndef json_min
|
||||
#define json_min(a, b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifndef json_max
|
||||
#define json_max(a, b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define JSON_FILE_BUF_SIZE 4096
|
||||
|
||||
/* utility functions */
|
||||
/**
|
||||
* Read the full contents of the given file, then convert it to a
|
||||
* json_object using json_tokener_parse().
|
||||
*
|
||||
* Returns NULL on failure. See json_util_get_last_err() for details.
|
||||
*/
|
||||
JSON_EXPORT struct json_object *json_object_from_file(const char *filename);
|
||||
|
||||
/**
|
||||
* Create a JSON object from already opened file descriptor.
|
||||
*
|
||||
* This function can be helpful, when you opened the file already,
|
||||
* e.g. when you have a temp file.
|
||||
* Note, that the fd must be readable at the actual position, i.e.
|
||||
* use lseek(fd, 0, SEEK_SET) before.
|
||||
*
|
||||
* The depth argument specifies the maximum object depth to pass to
|
||||
* json_tokener_new_ex(). When depth == -1, JSON_TOKENER_DEFAULT_DEPTH
|
||||
* is used instead.
|
||||
*
|
||||
* Returns NULL on failure. See json_util_get_last_err() for details.
|
||||
*/
|
||||
JSON_EXPORT struct json_object *json_object_from_fd_ex(int fd, int depth);
|
||||
|
||||
/**
|
||||
* Create a JSON object from an already opened file descriptor, using
|
||||
* the default maximum object depth. (JSON_TOKENER_DEFAULT_DEPTH)
|
||||
*
|
||||
* See json_object_from_fd_ex() for details.
|
||||
*/
|
||||
JSON_EXPORT struct json_object *json_object_from_fd(int fd);
|
||||
|
||||
/**
|
||||
* Equivalent to:
|
||||
* json_object_to_file_ext(filename, obj, JSON_C_TO_STRING_PLAIN);
|
||||
*
|
||||
* Returns -1 if something fails. See json_util_get_last_err() for details.
|
||||
*/
|
||||
JSON_EXPORT int json_object_to_file(const char *filename, struct json_object *obj);
|
||||
|
||||
/**
|
||||
* Open and truncate the given file, creating it if necessary, then
|
||||
* convert the json_object to a string and write it to the file.
|
||||
*
|
||||
* Returns -1 if something fails. See json_util_get_last_err() for details.
|
||||
*/
|
||||
JSON_EXPORT int json_object_to_file_ext(const char *filename, struct json_object *obj, int flags);
|
||||
|
||||
/**
|
||||
* Convert the json_object to a string and write it to the file descriptor.
|
||||
* Handles partial writes and will keep writing until done, or an error
|
||||
* occurs.
|
||||
*
|
||||
* @param fd an open, writable file descriptor to write to
|
||||
* @param obj the object to serializer and write
|
||||
* @param flags flags to pass to json_object_to_json_string_ext()
|
||||
* @return -1 if something fails. See json_util_get_last_err() for details.
|
||||
*/
|
||||
JSON_EXPORT int json_object_to_fd(int fd, struct json_object *obj, int flags);
|
||||
|
||||
/**
|
||||
* Return the last error from various json-c functions, including:
|
||||
* json_object_to_file{,_ext}, json_object_to_fd() or
|
||||
* json_object_from_{file,fd}, or NULL if there is none.
|
||||
*/
|
||||
JSON_EXPORT const char *json_util_get_last_err(void);
|
||||
|
||||
/* these parsing helpers return zero on success */
|
||||
JSON_EXPORT int json_parse_int64(const char *buf, int64_t *retval);
|
||||
JSON_EXPORT int json_parse_uint64(const char *buf, uint64_t *retval);
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
JSON_EXPORT int json_parse_double(const char *buf, double *retval);
|
||||
|
||||
/**
|
||||
* Return a string describing the type of the object.
|
||||
* e.g. "int", or "object", etc...
|
||||
*/
|
||||
JSON_EXPORT const char *json_type_to_name(enum json_type o_type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
101
thirdparty/include/json-c/json_visit.h
vendored
Normal file
101
thirdparty/include/json-c/json_visit.h
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
|
||||
#ifndef _json_c_json_visit_h_
|
||||
#define _json_c_json_visit_h_
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Methods for walking a tree of objects.
|
||||
*/
|
||||
#include "json_object.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef int(json_c_visit_userfunc)(json_object *jso, int flags, json_object *parent_jso,
|
||||
const char *jso_key, size_t *jso_index, void *userarg);
|
||||
|
||||
/**
|
||||
* Visit each object in the JSON hierarchy starting at jso.
|
||||
* For each object, userfunc is called, passing the object and userarg.
|
||||
* If the object has a parent (i.e. anything other than jso itself)
|
||||
* its parent will be passed as parent_jso, and either jso_key or jso_index
|
||||
* will be set, depending on whether the parent is an object or an array.
|
||||
*
|
||||
* Nodes will be visited depth first, but containers (arrays and objects)
|
||||
* will be visited twice, the second time with JSON_C_VISIT_SECOND set in
|
||||
* flags.
|
||||
*
|
||||
* userfunc must return one of the defined return values, to indicate
|
||||
* whether and how to continue visiting nodes, or one of various ways to stop.
|
||||
*
|
||||
* Returns 0 if nodes were visited successfully, even if some were
|
||||
* intentionally skipped due to what userfunc returned.
|
||||
* Returns <0 if an error occurred during iteration, including if
|
||||
* userfunc returned JSON_C_VISIT_RETURN_ERROR.
|
||||
*/
|
||||
JSON_EXPORT int json_c_visit(json_object *jso, int future_flags, json_c_visit_userfunc *userfunc,
|
||||
void *userarg);
|
||||
|
||||
/**
|
||||
* Passed to json_c_visit_userfunc as one of the flags values to indicate
|
||||
* that this is the second time a container (array or object) is being
|
||||
* called, after all of it's members have been iterated over.
|
||||
*/
|
||||
#define JSON_C_VISIT_SECOND 0x02
|
||||
|
||||
/**
|
||||
* This json_c_visit_userfunc return value indicates that iteration
|
||||
* should proceed normally.
|
||||
*/
|
||||
#define JSON_C_VISIT_RETURN_CONTINUE 0
|
||||
|
||||
/**
|
||||
* This json_c_visit_userfunc return value indicates that iteration
|
||||
* over the members of the current object should be skipped.
|
||||
* If the current object isn't a container (array or object), this
|
||||
* is no different than JSON_C_VISIT_RETURN_CONTINUE.
|
||||
*/
|
||||
#define JSON_C_VISIT_RETURN_SKIP 7547
|
||||
|
||||
/**
|
||||
* This json_c_visit_userfunc return value indicates that iteration
|
||||
* of the fields/elements of the <b>containing</b> object should stop
|
||||
* and continue "popped up" a level of the object hierarchy.
|
||||
* For example, returning this when handling arg will result in
|
||||
* arg3 and any other fields being skipped. The next call to userfunc
|
||||
* will be the JSON_C_VISIT_SECOND call on "foo", followed by a userfunc
|
||||
* call on "bar".
|
||||
* <pre>
|
||||
* {
|
||||
* "foo": {
|
||||
* "arg1": 1,
|
||||
* "arg2": 2,
|
||||
* "arg3": 3,
|
||||
* ...
|
||||
* },
|
||||
* "bar": {
|
||||
* ...
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
#define JSON_C_VISIT_RETURN_POP 767
|
||||
|
||||
/**
|
||||
* This json_c_visit_userfunc return value indicates that iteration
|
||||
* should stop immediately, and cause json_c_visit to return success.
|
||||
*/
|
||||
#define JSON_C_VISIT_RETURN_STOP 7867
|
||||
|
||||
/**
|
||||
* This json_c_visit_userfunc return value indicates that iteration
|
||||
* should stop immediately, and cause json_c_visit to return an error.
|
||||
*/
|
||||
#define JSON_C_VISIT_RETURN_ERROR -1
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _json_c_json_visit_h_ */
|
||||
369
thirdparty/include/json-c/linkhash.h
vendored
Normal file
369
thirdparty/include/json-c/linkhash.h
vendored
Normal file
@@ -0,0 +1,369 @@
|
||||
/*
|
||||
* $Id: linkhash.h,v 1.6 2006/01/30 23:07:57 mclark Exp $
|
||||
*
|
||||
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
|
||||
* Michael Clark <michael@metaparadigm.com>
|
||||
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See COPYING for details.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Internal methods for working with json_type_object objects. Although
|
||||
* this is exposed by the json_object_get_object() function and within the
|
||||
* json_object_iter type, it is not recommended for direct use.
|
||||
*/
|
||||
#ifndef _linkhash_h_
|
||||
#define _linkhash_h_
|
||||
|
||||
#include "json_object.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* golden prime used in hash functions
|
||||
*/
|
||||
#define LH_PRIME 0x9e370001UL
|
||||
|
||||
/**
|
||||
* The fraction of filled hash buckets until an insert will cause the table
|
||||
* to be resized.
|
||||
* This can range from just above 0 up to 1.0.
|
||||
*/
|
||||
#define LH_LOAD_FACTOR 0.66
|
||||
|
||||
/**
|
||||
* sentinel pointer value for empty slots
|
||||
*/
|
||||
#define LH_EMPTY (void *)-1
|
||||
|
||||
/**
|
||||
* sentinel pointer value for freed slots
|
||||
*/
|
||||
#define LH_FREED (void *)-2
|
||||
|
||||
/**
|
||||
* default string hash function
|
||||
*/
|
||||
#define JSON_C_STR_HASH_DFLT 0
|
||||
|
||||
/**
|
||||
* perl-like string hash function
|
||||
*/
|
||||
#define JSON_C_STR_HASH_PERLLIKE 1
|
||||
|
||||
/**
|
||||
* This function sets the hash function to be used for strings.
|
||||
* Must be one of the JSON_C_STR_HASH_* values.
|
||||
* @returns 0 - ok, -1 if parameter was invalid
|
||||
*/
|
||||
int json_global_set_string_hash(const int h);
|
||||
|
||||
struct lh_entry;
|
||||
|
||||
/**
|
||||
* callback function prototypes
|
||||
*/
|
||||
typedef void(lh_entry_free_fn)(struct lh_entry *e);
|
||||
/**
|
||||
* callback function prototypes
|
||||
*/
|
||||
typedef unsigned long(lh_hash_fn)(const void *k);
|
||||
/**
|
||||
* callback function prototypes
|
||||
*/
|
||||
typedef int(lh_equal_fn)(const void *k1, const void *k2);
|
||||
|
||||
/**
|
||||
* An entry in the hash table
|
||||
*/
|
||||
struct lh_entry
|
||||
{
|
||||
/**
|
||||
* The key. Use lh_entry_k() instead of accessing this directly.
|
||||
*/
|
||||
const void *k;
|
||||
/**
|
||||
* A flag for users of linkhash to know whether or not they
|
||||
* need to free k.
|
||||
*/
|
||||
int k_is_constant;
|
||||
/**
|
||||
* The value. Use lh_entry_v() instead of accessing this directly.
|
||||
*/
|
||||
const void *v;
|
||||
/**
|
||||
* The next entry
|
||||
*/
|
||||
struct lh_entry *next;
|
||||
/**
|
||||
* The previous entry.
|
||||
*/
|
||||
struct lh_entry *prev;
|
||||
};
|
||||
|
||||
/**
|
||||
* The hash table structure.
|
||||
*/
|
||||
struct lh_table
|
||||
{
|
||||
/**
|
||||
* Size of our hash.
|
||||
*/
|
||||
int size;
|
||||
/**
|
||||
* Numbers of entries.
|
||||
*/
|
||||
int count;
|
||||
|
||||
/**
|
||||
* The first entry.
|
||||
*/
|
||||
struct lh_entry *head;
|
||||
|
||||
/**
|
||||
* The last entry.
|
||||
*/
|
||||
struct lh_entry *tail;
|
||||
|
||||
struct lh_entry *table;
|
||||
|
||||
/**
|
||||
* A pointer onto the function responsible for freeing an entry.
|
||||
*/
|
||||
lh_entry_free_fn *free_fn;
|
||||
lh_hash_fn *hash_fn;
|
||||
lh_equal_fn *equal_fn;
|
||||
};
|
||||
typedef struct lh_table lh_table;
|
||||
|
||||
/**
|
||||
* Convenience list iterator.
|
||||
*/
|
||||
#define lh_foreach(table, entry) for (entry = table->head; entry; entry = entry->next)
|
||||
|
||||
/**
|
||||
* lh_foreach_safe allows calling of deletion routine while iterating.
|
||||
*
|
||||
* @param table a struct lh_table * to iterate over
|
||||
* @param entry a struct lh_entry * variable to hold each element
|
||||
* @param tmp a struct lh_entry * variable to hold a temporary pointer to the next element
|
||||
*/
|
||||
#define lh_foreach_safe(table, entry, tmp) \
|
||||
for (entry = table->head; entry && ((tmp = entry->next) || 1); entry = tmp)
|
||||
|
||||
/**
|
||||
* Create a new linkhash table.
|
||||
*
|
||||
* @param size initial table size. The table is automatically resized
|
||||
* although this incurs a performance penalty.
|
||||
* @param free_fn callback function used to free memory for entries
|
||||
* when lh_table_free or lh_table_delete is called.
|
||||
* If NULL is provided, then memory for keys and values
|
||||
* must be freed by the caller.
|
||||
* @param hash_fn function used to hash keys. 2 standard ones are defined:
|
||||
* lh_ptr_hash and lh_char_hash for hashing pointer values
|
||||
* and C strings respectively.
|
||||
* @param equal_fn comparison function to compare keys. 2 standard ones defined:
|
||||
* lh_ptr_hash and lh_char_hash for comparing pointer values
|
||||
* and C strings respectively.
|
||||
* @return On success, a pointer to the new linkhash table is returned.
|
||||
* On error, a null pointer is returned.
|
||||
*/
|
||||
extern struct lh_table *lh_table_new(int size, lh_entry_free_fn *free_fn, lh_hash_fn *hash_fn,
|
||||
lh_equal_fn *equal_fn);
|
||||
|
||||
/**
|
||||
* Convenience function to create a new linkhash table with char keys.
|
||||
*
|
||||
* @param size initial table size.
|
||||
* @param free_fn callback function used to free memory for entries.
|
||||
* @return On success, a pointer to the new linkhash table is returned.
|
||||
* On error, a null pointer is returned.
|
||||
*/
|
||||
extern struct lh_table *lh_kchar_table_new(int size, lh_entry_free_fn *free_fn);
|
||||
|
||||
/**
|
||||
* Convenience function to create a new linkhash table with ptr keys.
|
||||
*
|
||||
* @param size initial table size.
|
||||
* @param free_fn callback function used to free memory for entries.
|
||||
* @return On success, a pointer to the new linkhash table is returned.
|
||||
* On error, a null pointer is returned.
|
||||
*/
|
||||
extern struct lh_table *lh_kptr_table_new(int size, lh_entry_free_fn *free_fn);
|
||||
|
||||
/**
|
||||
* Free a linkhash table.
|
||||
*
|
||||
* If a lh_entry_free_fn callback free function was provided then it is
|
||||
* called for all entries in the table.
|
||||
*
|
||||
* @param t table to free.
|
||||
*/
|
||||
extern void lh_table_free(struct lh_table *t);
|
||||
|
||||
/**
|
||||
* Insert a record into the table.
|
||||
*
|
||||
* @param t the table to insert into.
|
||||
* @param k a pointer to the key to insert.
|
||||
* @param v a pointer to the value to insert.
|
||||
*
|
||||
* @return On success, <code>0</code> is returned.
|
||||
* On error, a negative value is returned.
|
||||
*/
|
||||
extern int lh_table_insert(struct lh_table *t, const void *k, const void *v);
|
||||
|
||||
/**
|
||||
* Insert a record into the table using a precalculated key hash.
|
||||
*
|
||||
* The hash h, which should be calculated with lh_get_hash() on k, is provided by
|
||||
* the caller, to allow for optimization when multiple operations with the same
|
||||
* key are known to be needed.
|
||||
*
|
||||
* @param t the table to insert into.
|
||||
* @param k a pointer to the key to insert.
|
||||
* @param v a pointer to the value to insert.
|
||||
* @param h hash value of the key to insert
|
||||
* @param opts if set to JSON_C_OBJECT_KEY_IS_CONSTANT, sets lh_entry.k_is_constant
|
||||
* so t's free function knows to avoid freeing the key.
|
||||
*/
|
||||
extern int lh_table_insert_w_hash(struct lh_table *t, const void *k, const void *v,
|
||||
const unsigned long h, const unsigned opts);
|
||||
|
||||
/**
|
||||
* Lookup a record in the table.
|
||||
*
|
||||
* @param t the table to lookup
|
||||
* @param k a pointer to the key to lookup
|
||||
* @return a pointer to the record structure of the value or NULL if it does not exist.
|
||||
*/
|
||||
extern struct lh_entry *lh_table_lookup_entry(struct lh_table *t, const void *k);
|
||||
|
||||
/**
|
||||
* Lookup a record in the table using a precalculated key hash.
|
||||
*
|
||||
* The hash h, which should be calculated with lh_get_hash() on k, is provided by
|
||||
* the caller, to allow for optimization when multiple operations with the same
|
||||
* key are known to be needed.
|
||||
*
|
||||
* @param t the table to lookup
|
||||
* @param k a pointer to the key to lookup
|
||||
* @param h hash value of the key to lookup
|
||||
* @return a pointer to the record structure of the value or NULL if it does not exist.
|
||||
*/
|
||||
extern struct lh_entry *lh_table_lookup_entry_w_hash(struct lh_table *t, const void *k,
|
||||
const unsigned long h);
|
||||
|
||||
/**
|
||||
* Lookup a record in the table.
|
||||
*
|
||||
* @param t the table to lookup
|
||||
* @param k a pointer to the key to lookup
|
||||
* @param v a pointer to a where to store the found value (set to NULL if it doesn't exist).
|
||||
* @return whether or not the key was found
|
||||
*/
|
||||
extern json_bool lh_table_lookup_ex(struct lh_table *t, const void *k, void **v);
|
||||
|
||||
/**
|
||||
* Delete a record from the table.
|
||||
*
|
||||
* If a callback free function is provided then it is called for the
|
||||
* for the item being deleted.
|
||||
* @param t the table to delete from.
|
||||
* @param e a pointer to the entry to delete.
|
||||
* @return 0 if the item was deleted.
|
||||
* @return -1 if it was not found.
|
||||
*/
|
||||
extern int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e);
|
||||
|
||||
/**
|
||||
* Delete a record from the table.
|
||||
*
|
||||
* If a callback free function is provided then it is called for the
|
||||
* for the item being deleted.
|
||||
* @param t the table to delete from.
|
||||
* @param k a pointer to the key to delete.
|
||||
* @return 0 if the item was deleted.
|
||||
* @return -1 if it was not found.
|
||||
*/
|
||||
extern int lh_table_delete(struct lh_table *t, const void *k);
|
||||
|
||||
extern int lh_table_length(struct lh_table *t);
|
||||
|
||||
/**
|
||||
* Resizes the specified table.
|
||||
*
|
||||
* @param t Pointer to table to resize.
|
||||
* @param new_size New table size. Must be positive.
|
||||
*
|
||||
* @return On success, <code>0</code> is returned.
|
||||
* On error, a negative value is returned.
|
||||
*/
|
||||
int lh_table_resize(struct lh_table *t, int new_size);
|
||||
|
||||
/**
|
||||
* @deprecated Don't use this outside of linkhash.h:
|
||||
*/
|
||||
#if (defined(AIX_CC) || (defined(_MSC_VER) && (_MSC_VER <= 1800)) )
|
||||
/* VS2010 can't handle inline funcs, so skip it there */
|
||||
#define _LH_INLINE
|
||||
#else
|
||||
#define _LH_INLINE inline
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Calculate the hash of a key for a given table.
|
||||
*
|
||||
* This is an exension to support functions that need to calculate
|
||||
* the hash several times and allows them to do it just once and then pass
|
||||
* in the hash to all utility functions. Depending on use case, this can be a
|
||||
* considerable performance improvement.
|
||||
* @param t the table (used to obtain hash function)
|
||||
* @param k a pointer to the key to lookup
|
||||
* @return the key's hash
|
||||
*/
|
||||
static _LH_INLINE unsigned long lh_get_hash(const struct lh_table *t, const void *k)
|
||||
{
|
||||
return t->hash_fn(k);
|
||||
}
|
||||
|
||||
#undef _LH_INLINE
|
||||
|
||||
/**
|
||||
* @deprecated Don't use this outside of linkhash.h:
|
||||
*/
|
||||
#ifdef __UNCONST
|
||||
#define _LH_UNCONST(a) __UNCONST(a)
|
||||
#else
|
||||
#define _LH_UNCONST(a) ((void *)(uintptr_t)(const void *)(a))
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Return a non-const version of lh_entry.k.
|
||||
*
|
||||
* lh_entry.k is const to indicate and help ensure that linkhash itself doesn't modify
|
||||
* it, but callers are allowed to do what they want with it.
|
||||
* See also lh_entry.k_is_constant
|
||||
*/
|
||||
#define lh_entry_k(entry) _LH_UNCONST((entry)->k)
|
||||
|
||||
/**
|
||||
* Return a non-const version of lh_entry.v.
|
||||
*
|
||||
* v is const to indicate and help ensure that linkhash itself doesn't modify
|
||||
* it, but callers are allowed to do what they want with it.
|
||||
*/
|
||||
#define lh_entry_v(entry) _LH_UNCONST((entry)->v)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
131
thirdparty/include/json-c/printbuf.h
vendored
Normal file
131
thirdparty/include/json-c/printbuf.h
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* $Id: printbuf.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
|
||||
*
|
||||
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
|
||||
* Michael Clark <michael@metaparadigm.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See COPYING for details.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
|
||||
* The copyrights to the contents of this file are licensed under the MIT License
|
||||
* (http://www.opensource.org/licenses/mit-license.php)
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Internal string buffer handing. Unless you're writing a
|
||||
* json_object_to_json_string_fn implementation for use with
|
||||
* json_object_set_serializer() direct use of this is not
|
||||
* recommended.
|
||||
*/
|
||||
#ifndef _printbuf_h_
|
||||
#define _printbuf_h_
|
||||
|
||||
#ifndef JSON_EXPORT
|
||||
#if defined(_MSC_VER)
|
||||
#define JSON_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define JSON_EXPORT extern
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct printbuf
|
||||
{
|
||||
char *buf;
|
||||
int bpos;
|
||||
int size;
|
||||
};
|
||||
typedef struct printbuf printbuf;
|
||||
|
||||
JSON_EXPORT struct printbuf *printbuf_new(void);
|
||||
|
||||
/* As an optimization, printbuf_memappend_fast() is defined as a macro
|
||||
* that handles copying data if the buffer is large enough; otherwise
|
||||
* it invokes printbuf_memappend() which performs the heavy
|
||||
* lifting of realloc()ing the buffer and copying data.
|
||||
*
|
||||
* Your code should not use printbuf_memappend() directly unless it
|
||||
* checks the return code. Use printbuf_memappend_fast() instead.
|
||||
*/
|
||||
JSON_EXPORT int printbuf_memappend(struct printbuf *p, const char *buf, int size);
|
||||
|
||||
#define printbuf_memappend_fast(p, bufptr, bufsize) \
|
||||
do \
|
||||
{ \
|
||||
if ((p->size - p->bpos) > bufsize) \
|
||||
{ \
|
||||
memcpy(p->buf + p->bpos, (bufptr), bufsize); \
|
||||
p->bpos += bufsize; \
|
||||
p->buf[p->bpos] = '\0'; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
printbuf_memappend(p, (bufptr), bufsize); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define printbuf_length(p) ((p)->bpos)
|
||||
|
||||
/**
|
||||
* Results in a compile error if the argument is not a string literal.
|
||||
*/
|
||||
#define _printbuf_check_literal(mystr) ("" mystr)
|
||||
|
||||
/**
|
||||
* This is an optimization wrapper around printbuf_memappend() that is useful
|
||||
* for appending string literals. Since the size of string constants is known
|
||||
* at compile time, using this macro can avoid a costly strlen() call. This is
|
||||
* especially helpful when a constant string must be appended many times. If
|
||||
* you got here because of a compilation error caused by passing something
|
||||
* other than a string literal, use printbuf_memappend_fast() in conjunction
|
||||
* with strlen().
|
||||
*
|
||||
* See also:
|
||||
* printbuf_memappend_fast()
|
||||
* printbuf_memappend()
|
||||
* sprintbuf()
|
||||
*/
|
||||
#define printbuf_strappend(pb, str) \
|
||||
printbuf_memappend((pb), _printbuf_check_literal(str), sizeof(str) - 1)
|
||||
|
||||
/**
|
||||
* Set len bytes of the buffer to charvalue, starting at offset offset.
|
||||
* Similar to calling memset(x, charvalue, len);
|
||||
*
|
||||
* The memory allocated for the buffer is extended as necessary.
|
||||
*
|
||||
* If offset is -1, this starts at the end of the current data in the buffer.
|
||||
*/
|
||||
JSON_EXPORT int printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len);
|
||||
|
||||
/**
|
||||
* Formatted print to printbuf.
|
||||
*
|
||||
* This function is the most expensive of the available functions for appending
|
||||
* string data to a printbuf and should be used only where convenience is more
|
||||
* important than speed. Avoid using this function in high performance code or
|
||||
* tight loops; in these scenarios, consider using snprintf() with a static
|
||||
* buffer in conjunction with one of the printbuf_*append() functions.
|
||||
*
|
||||
* See also:
|
||||
* printbuf_memappend_fast()
|
||||
* printbuf_memappend()
|
||||
* printbuf_strappend()
|
||||
*/
|
||||
JSON_EXPORT int sprintbuf(struct printbuf *p, const char *msg, ...);
|
||||
|
||||
JSON_EXPORT void printbuf_reset(struct printbuf *p);
|
||||
|
||||
JSON_EXPORT void printbuf_free(struct printbuf *p);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
45
thirdparty/include/libevent/evdns.h
vendored
Normal file
45
thirdparty/include/libevent/evdns.h
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
#ifndef EVENT1_EVDNS_H_INCLUDED_
|
||||
#define EVENT1_EVDNS_H_INCLUDED_
|
||||
|
||||
/** @file evdns.h
|
||||
|
||||
A dns subsystem for Libevent.
|
||||
|
||||
The <evdns.h> header is deprecated in Libevent 2.0 and later; please
|
||||
use <event2/evdns.h> instead. Depending on what functionality you
|
||||
need, you may also want to include more of the other <event2/...>
|
||||
headers.
|
||||
*/
|
||||
|
||||
#include <event.h>
|
||||
#include <event2/dns.h>
|
||||
#include <event2/dns_compat.h>
|
||||
#include <event2/dns_struct.h>
|
||||
|
||||
#endif /* EVENT1_EVDNS_H_INCLUDED_ */
|
||||
83
thirdparty/include/libevent/event.h
vendored
Normal file
83
thirdparty/include/libevent/event.h
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
#ifndef EVENT1_EVENT_H_INCLUDED_
|
||||
#define EVENT1_EVENT_H_INCLUDED_
|
||||
|
||||
/** @file event.h
|
||||
|
||||
A library for writing event-driven network servers.
|
||||
|
||||
The <event.h> header is deprecated in Libevent 2.0 and later; please
|
||||
use <event2/event.h> instead. Depending on what functionality you
|
||||
need, you may also want to include more of the other event2/
|
||||
headers.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <event2/event-config.h>
|
||||
#ifdef EVENT__HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef EVENT__HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#ifdef EVENT__HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#include <stdarg.h>
|
||||
|
||||
/* For int types. */
|
||||
#include <evutil.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#include <event2/event_struct.h>
|
||||
#include <event2/event.h>
|
||||
#include <event2/event_compat.h>
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/buffer_compat.h>
|
||||
#include <event2/bufferevent.h>
|
||||
#include <event2/bufferevent_struct.h>
|
||||
#include <event2/bufferevent_compat.h>
|
||||
#include <event2/tag.h>
|
||||
#include <event2/tag_compat.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EVENT1_EVENT_H_INCLUDED_ */
|
||||
1077
thirdparty/include/libevent/event2/buffer.h
vendored
Normal file
1077
thirdparty/include/libevent/event2/buffer.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
116
thirdparty/include/libevent/event2/buffer_compat.h
vendored
Normal file
116
thirdparty/include/libevent/event2/buffer_compat.h
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
|
||||
#ifndef EVENT2_BUFFER_COMPAT_H_INCLUDED_
|
||||
#define EVENT2_BUFFER_COMPAT_H_INCLUDED_
|
||||
|
||||
#include <event2/visibility.h>
|
||||
|
||||
/** @file event2/buffer_compat.h
|
||||
|
||||
Obsolete and deprecated versions of the functions in buffer.h: provided
|
||||
only for backward compatibility.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
Obsolete alias for evbuffer_readln(buffer, NULL, EVBUFFER_EOL_ANY).
|
||||
|
||||
@deprecated This function is deprecated because its behavior is not correct
|
||||
for almost any protocol, and also because it's wholly subsumed by
|
||||
evbuffer_readln().
|
||||
|
||||
@param buffer the evbuffer to read from
|
||||
@return pointer to a single line, or NULL if an error occurred
|
||||
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
char *evbuffer_readline(struct evbuffer *buffer);
|
||||
|
||||
/** Type definition for a callback that is invoked whenever data is added or
|
||||
removed from an evbuffer.
|
||||
|
||||
An evbuffer may have one or more callbacks set at a time. The order
|
||||
in which they are executed is undefined.
|
||||
|
||||
A callback function may add more callbacks, or remove itself from the
|
||||
list of callbacks, or add or remove data from the buffer. It may not
|
||||
remove another callback from the list.
|
||||
|
||||
If a callback adds or removes data from the buffer or from another
|
||||
buffer, this can cause a recursive invocation of your callback or
|
||||
other callbacks. If you ask for an infinite loop, you might just get
|
||||
one: watch out!
|
||||
|
||||
@param buffer the buffer whose size has changed
|
||||
@param old_len the previous length of the buffer
|
||||
@param new_len the current length of the buffer
|
||||
@param arg a pointer to user data
|
||||
*/
|
||||
typedef void (*evbuffer_cb)(struct evbuffer *buffer, size_t old_len, size_t new_len, void *arg);
|
||||
|
||||
/**
|
||||
Replace all callbacks on an evbuffer with a single new callback, or
|
||||
remove them.
|
||||
|
||||
Subsequent calls to evbuffer_setcb() replace callbacks set by previous
|
||||
calls. Setting the callback to NULL removes any previously set callback.
|
||||
|
||||
@deprecated This function is deprecated because it clears all previous
|
||||
callbacks set on the evbuffer, which can cause confusing behavior if
|
||||
multiple parts of the code all want to add their own callbacks on a
|
||||
buffer. Instead, use evbuffer_add(), evbuffer_del(), and
|
||||
evbuffer_setflags() to manage your own evbuffer callbacks without
|
||||
interfering with callbacks set by others.
|
||||
|
||||
@param buffer the evbuffer to be monitored
|
||||
@param cb the callback function to invoke when the evbuffer is modified,
|
||||
or NULL to remove all callbacks.
|
||||
@param cbarg an argument to be provided to the callback function
|
||||
@return 0 if successful, or -1 on error
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evbuffer_setcb(struct evbuffer *buffer, evbuffer_cb cb, void *cbarg);
|
||||
|
||||
|
||||
/**
|
||||
Find a string within an evbuffer.
|
||||
|
||||
@param buffer the evbuffer to be searched
|
||||
@param what the string to be searched for
|
||||
@param len the length of the search string
|
||||
@return a pointer to the beginning of the search string, or NULL if the search failed.
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
unsigned char *evbuffer_find(struct evbuffer *buffer, const unsigned char *what, size_t len);
|
||||
|
||||
/** deprecated in favor of calling the functions directly */
|
||||
#define EVBUFFER_LENGTH(x) evbuffer_get_length(x)
|
||||
/** deprecated in favor of calling the functions directly */
|
||||
#define EVBUFFER_DATA(x) evbuffer_pullup((x), -1)
|
||||
|
||||
#endif
|
||||
|
||||
1024
thirdparty/include/libevent/event2/bufferevent.h
vendored
Normal file
1024
thirdparty/include/libevent/event2/bufferevent.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
104
thirdparty/include/libevent/event2/bufferevent_compat.h
vendored
Normal file
104
thirdparty/include/libevent/event2/bufferevent_compat.h
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 2007-2012 Niels Provos, Nick Mathewson
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
#ifndef EVENT2_BUFFEREVENT_COMPAT_H_INCLUDED_
|
||||
#define EVENT2_BUFFEREVENT_COMPAT_H_INCLUDED_
|
||||
|
||||
#include <event2/visibility.h>
|
||||
|
||||
#define evbuffercb bufferevent_data_cb
|
||||
#define everrorcb bufferevent_event_cb
|
||||
|
||||
/**
|
||||
Create a new bufferevent for an fd.
|
||||
|
||||
This function is deprecated. Use bufferevent_socket_new and
|
||||
bufferevent_set_callbacks instead.
|
||||
|
||||
Libevent provides an abstraction on top of the regular event callbacks.
|
||||
This abstraction is called a buffered event. A buffered event provides
|
||||
input and output buffers that get filled and drained automatically. The
|
||||
user of a buffered event no longer deals directly with the I/O, but
|
||||
instead is reading from input and writing to output buffers.
|
||||
|
||||
Once initialized, the bufferevent structure can be used repeatedly with
|
||||
bufferevent_enable() and bufferevent_disable().
|
||||
|
||||
When read enabled the bufferevent will try to read from the file descriptor
|
||||
and call the read callback. The write callback is executed whenever the
|
||||
output buffer is drained below the write low watermark, which is 0 by
|
||||
default.
|
||||
|
||||
If multiple bases are in use, bufferevent_base_set() must be called before
|
||||
enabling the bufferevent for the first time.
|
||||
|
||||
@deprecated This function is deprecated because it uses the current
|
||||
event base, and as such can be error prone for multithreaded programs.
|
||||
Use bufferevent_socket_new() instead.
|
||||
|
||||
@param fd the file descriptor from which data is read and written to.
|
||||
This file descriptor is not allowed to be a pipe(2).
|
||||
@param readcb callback to invoke when there is data to be read, or NULL if
|
||||
no callback is desired
|
||||
@param writecb callback to invoke when the file descriptor is ready for
|
||||
writing, or NULL if no callback is desired
|
||||
@param errorcb callback to invoke when there is an error on the file
|
||||
descriptor
|
||||
@param cbarg an argument that will be supplied to each of the callbacks
|
||||
(readcb, writecb, and errorcb)
|
||||
@return a pointer to a newly allocated bufferevent struct, or NULL if an
|
||||
error occurred
|
||||
@see bufferevent_base_set(), bufferevent_free()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
struct bufferevent *bufferevent_new(evutil_socket_t fd,
|
||||
evbuffercb readcb, evbuffercb writecb, everrorcb errorcb, void *cbarg);
|
||||
|
||||
|
||||
/**
|
||||
Set the read and write timeout for a buffered event.
|
||||
|
||||
@param bufev the bufferevent to be modified
|
||||
@param timeout_read the read timeout
|
||||
@param timeout_write the write timeout
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void bufferevent_settimeout(struct bufferevent *bufev,
|
||||
int timeout_read, int timeout_write);
|
||||
|
||||
#define EVBUFFER_READ BEV_EVENT_READING
|
||||
#define EVBUFFER_WRITE BEV_EVENT_WRITING
|
||||
#define EVBUFFER_EOF BEV_EVENT_EOF
|
||||
#define EVBUFFER_ERROR BEV_EVENT_ERROR
|
||||
#define EVBUFFER_TIMEOUT BEV_EVENT_TIMEOUT
|
||||
|
||||
/** macro for getting access to the input buffer of a bufferevent */
|
||||
#define EVBUFFER_INPUT(x) bufferevent_get_input(x)
|
||||
/** macro for getting access to the output buffer of a bufferevent */
|
||||
#define EVBUFFER_OUTPUT(x) bufferevent_get_output(x)
|
||||
|
||||
#endif
|
||||
134
thirdparty/include/libevent/event2/bufferevent_ssl.h
vendored
Normal file
134
thirdparty/include/libevent/event2/bufferevent_ssl.h
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2012 Niels Provos and Nick Mathewson
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
#ifndef EVENT2_BUFFEREVENT_SSL_H_INCLUDED_
|
||||
#define EVENT2_BUFFEREVENT_SSL_H_INCLUDED_
|
||||
|
||||
/** @file event2/bufferevent_ssl.h
|
||||
|
||||
OpenSSL support for bufferevents.
|
||||
*/
|
||||
#include <event2/visibility.h>
|
||||
#include <event2/event-config.h>
|
||||
#include <event2/bufferevent.h>
|
||||
#include <event2/util.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* This is what openssl's SSL objects are underneath. */
|
||||
struct ssl_st;
|
||||
|
||||
/**
|
||||
The state of an SSL object to be used when creating a new
|
||||
SSL bufferevent.
|
||||
*/
|
||||
enum bufferevent_ssl_state {
|
||||
BUFFEREVENT_SSL_OPEN = 0,
|
||||
BUFFEREVENT_SSL_CONNECTING = 1,
|
||||
BUFFEREVENT_SSL_ACCEPTING = 2
|
||||
};
|
||||
|
||||
#if defined(EVENT__HAVE_OPENSSL) || defined(EVENT_IN_DOXYGEN_)
|
||||
/**
|
||||
Create a new SSL bufferevent to send its data over another bufferevent.
|
||||
|
||||
@param base An event_base to use to detect reading and writing. It
|
||||
must also be the base for the underlying bufferevent.
|
||||
@param underlying A socket to use for this SSL
|
||||
@param ssl A SSL* object from openssl.
|
||||
@param state The current state of the SSL connection
|
||||
@param options One or more bufferevent_options
|
||||
@return A new bufferevent on success, or NULL on failure
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
struct bufferevent *
|
||||
bufferevent_openssl_filter_new(struct event_base *base,
|
||||
struct bufferevent *underlying,
|
||||
struct ssl_st *ssl,
|
||||
enum bufferevent_ssl_state state,
|
||||
int options);
|
||||
|
||||
/**
|
||||
Create a new SSL bufferevent to send its data over an SSL * on a socket.
|
||||
|
||||
@param base An event_base to use to detect reading and writing
|
||||
@param fd A socket to use for this SSL
|
||||
@param ssl A SSL* object from openssl.
|
||||
@param state The current state of the SSL connection
|
||||
@param options One or more bufferevent_options
|
||||
@return A new bufferevent on success, or NULL on failure.
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
struct bufferevent *
|
||||
bufferevent_openssl_socket_new(struct event_base *base,
|
||||
evutil_socket_t fd,
|
||||
struct ssl_st *ssl,
|
||||
enum bufferevent_ssl_state state,
|
||||
int options);
|
||||
|
||||
/** Control how to report dirty SSL shutdowns.
|
||||
|
||||
If the peer (or the network, or an attacker) closes the TCP
|
||||
connection before closing the SSL channel, and the protocol is SSL >= v3,
|
||||
this is a "dirty" shutdown. If allow_dirty_shutdown is 0 (default),
|
||||
this is reported as BEV_EVENT_ERROR.
|
||||
|
||||
If instead allow_dirty_shutdown=1, a dirty shutdown is reported as
|
||||
BEV_EVENT_EOF.
|
||||
|
||||
(Note that if the protocol is < SSLv3, you will always receive
|
||||
BEV_EVENT_EOF, since SSL 2 and earlier cannot distinguish a secure
|
||||
connection close from a dirty one. This is one reason (among many)
|
||||
not to use SSL 2.)
|
||||
*/
|
||||
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int bufferevent_openssl_get_allow_dirty_shutdown(struct bufferevent *bev);
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void bufferevent_openssl_set_allow_dirty_shutdown(struct bufferevent *bev,
|
||||
int allow_dirty_shutdown);
|
||||
|
||||
/** Return the underlying openssl SSL * object for an SSL bufferevent. */
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
struct ssl_st *
|
||||
bufferevent_openssl_get_ssl(struct bufferevent *bufev);
|
||||
|
||||
/** Tells a bufferevent to begin SSL renegotiation. */
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int bufferevent_ssl_renegotiate(struct bufferevent *bev);
|
||||
|
||||
/** Return the most recent OpenSSL error reported on an SSL bufferevent. */
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
unsigned long bufferevent_get_openssl_error(struct bufferevent *bev);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EVENT2_BUFFEREVENT_SSL_H_INCLUDED_ */
|
||||
116
thirdparty/include/libevent/event2/bufferevent_struct.h
vendored
Normal file
116
thirdparty/include/libevent/event2/bufferevent_struct.h
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
#ifndef EVENT2_BUFFEREVENT_STRUCT_H_INCLUDED_
|
||||
#define EVENT2_BUFFEREVENT_STRUCT_H_INCLUDED_
|
||||
|
||||
/** @file event2/bufferevent_struct.h
|
||||
|
||||
Data structures for bufferevents. Using these structures may hurt forward
|
||||
compatibility with later versions of Libevent: be careful!
|
||||
|
||||
@deprecated Use of bufferevent_struct.h is completely deprecated; these
|
||||
structures are only exposed for backward compatibility with programs
|
||||
written before Libevent 2.0 that used them.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <event2/event-config.h>
|
||||
#ifdef EVENT__HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef EVENT__HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
/* For int types. */
|
||||
#include <event2/util.h>
|
||||
/* For struct event */
|
||||
#include <event2/event_struct.h>
|
||||
|
||||
struct event_watermark {
|
||||
size_t low;
|
||||
size_t high;
|
||||
};
|
||||
|
||||
/**
|
||||
Shared implementation of a bufferevent.
|
||||
|
||||
This type is exposed only because it was exposed in previous versions,
|
||||
and some people's code may rely on manipulating it. Otherwise, you
|
||||
should really not rely on the layout, size, or contents of this structure:
|
||||
it is fairly volatile, and WILL change in future versions of the code.
|
||||
**/
|
||||
struct bufferevent {
|
||||
/** Event base for which this bufferevent was created. */
|
||||
struct event_base *ev_base;
|
||||
/** Pointer to a table of function pointers to set up how this
|
||||
bufferevent behaves. */
|
||||
const struct bufferevent_ops *be_ops;
|
||||
|
||||
/** A read event that triggers when a timeout has happened or a socket
|
||||
is ready to read data. Only used by some subtypes of
|
||||
bufferevent. */
|
||||
struct event ev_read;
|
||||
/** A write event that triggers when a timeout has happened or a socket
|
||||
is ready to write data. Only used by some subtypes of
|
||||
bufferevent. */
|
||||
struct event ev_write;
|
||||
|
||||
/** An input buffer. Only the bufferevent is allowed to add data to
|
||||
this buffer, though the user is allowed to drain it. */
|
||||
struct evbuffer *input;
|
||||
|
||||
/** An input buffer. Only the bufferevent is allowed to drain data
|
||||
from this buffer, though the user is allowed to add it. */
|
||||
struct evbuffer *output;
|
||||
|
||||
struct event_watermark wm_read;
|
||||
struct event_watermark wm_write;
|
||||
|
||||
bufferevent_data_cb readcb;
|
||||
bufferevent_data_cb writecb;
|
||||
/* This should be called 'eventcb', but renaming it would break
|
||||
* backward compatibility */
|
||||
bufferevent_event_cb errorcb;
|
||||
void *cbarg;
|
||||
|
||||
struct timeval timeout_read;
|
||||
struct timeval timeout_write;
|
||||
|
||||
/** Events that are currently enabled: currently EV_READ and EV_WRITE
|
||||
are supported. */
|
||||
short enabled;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EVENT2_BUFFEREVENT_STRUCT_H_INCLUDED_ */
|
||||
751
thirdparty/include/libevent/event2/dns.h
vendored
Normal file
751
thirdparty/include/libevent/event2/dns.h
vendored
Normal file
@@ -0,0 +1,751 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The original DNS code is due to Adam Langley with heavy
|
||||
* modifications by Nick Mathewson. Adam put his DNS software in the
|
||||
* public domain. You can find his original copyright below. Please,
|
||||
* aware that the code as part of Libevent is governed by the 3-clause
|
||||
* BSD license above.
|
||||
*
|
||||
* This software is Public Domain. To view a copy of the public domain dedication,
|
||||
* visit http://creativecommons.org/licenses/publicdomain/ or send a letter to
|
||||
* Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
|
||||
*
|
||||
* I ask and expect, but do not require, that all derivative works contain an
|
||||
* attribution similar to:
|
||||
* Parts developed by Adam Langley <agl@imperialviolet.org>
|
||||
*
|
||||
* You may wish to replace the word "Parts" with something else depending on
|
||||
* the amount of original code.
|
||||
*
|
||||
* (Derivative works does not include programs which link against, run or include
|
||||
* the source verbatim in their source distributions)
|
||||
*/
|
||||
|
||||
/** @file event2/dns.h
|
||||
*
|
||||
* Welcome, gentle reader
|
||||
*
|
||||
* Async DNS lookups are really a whole lot harder than they should be,
|
||||
* mostly stemming from the fact that the libc resolver has never been
|
||||
* very good at them. Before you use this library you should see if libc
|
||||
* can do the job for you with the modern async call getaddrinfo_a
|
||||
* (see http://www.imperialviolet.org/page25.html#e498). Otherwise,
|
||||
* please continue.
|
||||
*
|
||||
* The library keeps track of the state of nameservers and will avoid
|
||||
* them when they go down. Otherwise it will round robin between them.
|
||||
*
|
||||
* Quick start guide:
|
||||
* #include "evdns.h"
|
||||
* void callback(int result, char type, int count, int ttl,
|
||||
* void *addresses, void *arg);
|
||||
* evdns_resolv_conf_parse(DNS_OPTIONS_ALL, "/etc/resolv.conf");
|
||||
* evdns_resolve("www.hostname.com", 0, callback, NULL);
|
||||
*
|
||||
* When the lookup is complete the callback function is called. The
|
||||
* first argument will be one of the DNS_ERR_* defines in evdns.h.
|
||||
* Hopefully it will be DNS_ERR_NONE, in which case type will be
|
||||
* DNS_IPv4_A, count will be the number of IP addresses, ttl is the time
|
||||
* which the data can be cached for (in seconds), addresses will point
|
||||
* to an array of uint32_t's and arg will be whatever you passed to
|
||||
* evdns_resolve.
|
||||
*
|
||||
* Searching:
|
||||
*
|
||||
* In order for this library to be a good replacement for glibc's resolver it
|
||||
* supports searching. This involves setting a list of default domains, in
|
||||
* which names will be queried for. The number of dots in the query name
|
||||
* determines the order in which this list is used.
|
||||
*
|
||||
* Searching appears to be a single lookup from the point of view of the API,
|
||||
* although many DNS queries may be generated from a single call to
|
||||
* evdns_resolve. Searching can also drastically slow down the resolution
|
||||
* of names.
|
||||
*
|
||||
* To disable searching:
|
||||
* 1. Never set it up. If you never call evdns_resolv_conf_parse or
|
||||
* evdns_search_add then no searching will occur.
|
||||
*
|
||||
* 2. If you do call evdns_resolv_conf_parse then don't pass
|
||||
* DNS_OPTION_SEARCH (or DNS_OPTIONS_ALL, which implies it).
|
||||
*
|
||||
* 3. When calling evdns_resolve, pass the DNS_QUERY_NO_SEARCH flag.
|
||||
*
|
||||
* The order of searches depends on the number of dots in the name. If the
|
||||
* number is greater than the ndots setting then the names is first tried
|
||||
* globally. Otherwise each search domain is appended in turn.
|
||||
*
|
||||
* The ndots setting can either be set from a resolv.conf, or by calling
|
||||
* evdns_search_ndots_set.
|
||||
*
|
||||
* For example, with ndots set to 1 (the default) and a search domain list of
|
||||
* ["myhome.net"]:
|
||||
* Query: www
|
||||
* Order: www.myhome.net, www.
|
||||
*
|
||||
* Query: www.abc
|
||||
* Order: www.abc., www.abc.myhome.net
|
||||
*
|
||||
* Internals:
|
||||
*
|
||||
* Requests are kept in two queues. The first is the inflight queue. In
|
||||
* this queue requests have an allocated transaction id and nameserver.
|
||||
* They will soon be transmitted if they haven't already been.
|
||||
*
|
||||
* The second is the waiting queue. The size of the inflight ring is
|
||||
* limited and all other requests wait in waiting queue for space. This
|
||||
* bounds the number of concurrent requests so that we don't flood the
|
||||
* nameserver. Several algorithms require a full walk of the inflight
|
||||
* queue and so bounding its size keeps thing going nicely under huge
|
||||
* (many thousands of requests) loads.
|
||||
*
|
||||
* If a nameserver loses too many requests it is considered down and we
|
||||
* try not to use it. After a while we send a probe to that nameserver
|
||||
* (a lookup for google.com) and, if it replies, we consider it working
|
||||
* again. If the nameserver fails a probe we wait longer to try again
|
||||
* with the next probe.
|
||||
*/
|
||||
|
||||
#ifndef EVENT2_DNS_H_INCLUDED_
|
||||
#define EVENT2_DNS_H_INCLUDED_
|
||||
|
||||
#include <event2/visibility.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* For integer types. */
|
||||
#include <event2/util.h>
|
||||
|
||||
/** Error codes 0-5 are as described in RFC 1035. */
|
||||
#define DNS_ERR_NONE 0
|
||||
/** The name server was unable to interpret the query */
|
||||
#define DNS_ERR_FORMAT 1
|
||||
/** The name server was unable to process this query due to a problem with the
|
||||
* name server */
|
||||
#define DNS_ERR_SERVERFAILED 2
|
||||
/** The domain name does not exist */
|
||||
#define DNS_ERR_NOTEXIST 3
|
||||
/** The name server does not support the requested kind of query */
|
||||
#define DNS_ERR_NOTIMPL 4
|
||||
/** The name server refuses to reform the specified operation for policy
|
||||
* reasons */
|
||||
#define DNS_ERR_REFUSED 5
|
||||
/** The reply was truncated or ill-formatted */
|
||||
#define DNS_ERR_TRUNCATED 65
|
||||
/** An unknown error occurred */
|
||||
#define DNS_ERR_UNKNOWN 66
|
||||
/** Communication with the server timed out */
|
||||
#define DNS_ERR_TIMEOUT 67
|
||||
/** The request was canceled because the DNS subsystem was shut down. */
|
||||
#define DNS_ERR_SHUTDOWN 68
|
||||
/** The request was canceled via a call to evdns_cancel_request */
|
||||
#define DNS_ERR_CANCEL 69
|
||||
/** There were no answers and no error condition in the DNS packet.
|
||||
* This can happen when you ask for an address that exists, but a record
|
||||
* type that doesn't. */
|
||||
#define DNS_ERR_NODATA 70
|
||||
|
||||
#define DNS_IPv4_A 1
|
||||
#define DNS_PTR 2
|
||||
#define DNS_IPv6_AAAA 3
|
||||
|
||||
#define DNS_QUERY_NO_SEARCH 1
|
||||
|
||||
/* Allow searching */
|
||||
#define DNS_OPTION_SEARCH 1
|
||||
/* Parse "nameserver" and add default if no such section */
|
||||
#define DNS_OPTION_NAMESERVERS 2
|
||||
/* Parse additional options like:
|
||||
* - timeout:
|
||||
* - getaddrinfo-allow-skew:
|
||||
* - max-timeouts:
|
||||
* - max-inflight:
|
||||
* - attempts:
|
||||
* - randomize-case:
|
||||
* - initial-probe-timeout:
|
||||
*/
|
||||
#define DNS_OPTION_MISC 4
|
||||
/* Load hosts file (i.e. "/etc/hosts") */
|
||||
#define DNS_OPTION_HOSTSFILE 8
|
||||
/**
|
||||
* All above:
|
||||
* - DNS_OPTION_SEARCH
|
||||
* - DNS_OPTION_NAMESERVERS
|
||||
* - DNS_OPTION_MISC
|
||||
* - DNS_OPTION_HOSTSFILE
|
||||
*/
|
||||
#define DNS_OPTIONS_ALL ( \
|
||||
DNS_OPTION_SEARCH | \
|
||||
DNS_OPTION_NAMESERVERS | \
|
||||
DNS_OPTION_MISC | \
|
||||
DNS_OPTION_HOSTSFILE | \
|
||||
0 \
|
||||
)
|
||||
/* Do not "default" nameserver (i.e. "127.0.0.1:53") if there is no nameservers
|
||||
* in resolv.conf, (iff DNS_OPTION_NAMESERVERS is set) */
|
||||
#define DNS_OPTION_NAMESERVERS_NO_DEFAULT 16
|
||||
|
||||
/* Obsolete name for DNS_QUERY_NO_SEARCH */
|
||||
#define DNS_NO_SEARCH DNS_QUERY_NO_SEARCH
|
||||
|
||||
/**
|
||||
* The callback that contains the results from a lookup.
|
||||
* - result is one of the DNS_ERR_* values (DNS_ERR_NONE for success)
|
||||
* - type is either DNS_IPv4_A or DNS_PTR or DNS_IPv6_AAAA
|
||||
* - count contains the number of addresses of form type
|
||||
* - ttl is the number of seconds the resolution may be cached for.
|
||||
* - addresses needs to be cast according to type. It will be an array of
|
||||
* 4-byte sequences for ipv4, or an array of 16-byte sequences for ipv6,
|
||||
* or a nul-terminated string for PTR.
|
||||
*/
|
||||
typedef void (*evdns_callback_type) (int result, char type, int count, int ttl, void *addresses, void *arg);
|
||||
|
||||
struct evdns_base;
|
||||
struct event_base;
|
||||
|
||||
/** Flag for evdns_base_new: process resolv.conf. */
|
||||
#define EVDNS_BASE_INITIALIZE_NAMESERVERS 1
|
||||
/** Flag for evdns_base_new: Do not prevent the libevent event loop from
|
||||
* exiting when we have no active dns requests. */
|
||||
#define EVDNS_BASE_DISABLE_WHEN_INACTIVE 0x8000
|
||||
/** Flag for evdns_base_new: If EVDNS_BASE_INITIALIZE_NAMESERVERS isset, do not
|
||||
* add default nameserver if there are no nameservers in resolv.conf
|
||||
* @see DNS_OPTION_NAMESERVERS_NO_DEFAULT */
|
||||
#define EVDNS_BASE_NAMESERVERS_NO_DEFAULT 0x10000
|
||||
|
||||
/**
|
||||
Initialize the asynchronous DNS library.
|
||||
|
||||
This function initializes support for non-blocking name resolution by
|
||||
calling evdns_resolv_conf_parse() on UNIX and
|
||||
evdns_config_windows_nameservers() on Windows.
|
||||
|
||||
@param event_base the event base to associate the dns client with
|
||||
@param flags any of EVDNS_BASE_INITIALIZE_NAMESERVERS|
|
||||
EVDNS_BASE_DISABLE_WHEN_INACTIVE|EVDNS_BASE_NAMESERVERS_NO_DEFAULT
|
||||
@return evdns_base object if successful, or NULL if an error occurred.
|
||||
@see evdns_base_free()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
struct evdns_base * evdns_base_new(struct event_base *event_base, int initialize_nameservers);
|
||||
|
||||
|
||||
/**
|
||||
Shut down the asynchronous DNS resolver and terminate all active requests.
|
||||
|
||||
If the 'fail_requests' option is enabled, all active requests will return
|
||||
an empty result with the error flag set to DNS_ERR_SHUTDOWN. Otherwise,
|
||||
the requests will be silently discarded.
|
||||
|
||||
@param evdns_base the evdns base to free
|
||||
@param fail_requests if zero, active requests will be aborted; if non-zero,
|
||||
active requests will return DNS_ERR_SHUTDOWN.
|
||||
@see evdns_base_new()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evdns_base_free(struct evdns_base *base, int fail_requests);
|
||||
|
||||
/**
|
||||
Remove all hosts entries that have been loaded into the event_base via
|
||||
evdns_base_load_hosts or via event_base_resolv_conf_parse.
|
||||
|
||||
@param evdns_base the evdns base to remove outdated host addresses from
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evdns_base_clear_host_addresses(struct evdns_base *base);
|
||||
|
||||
/**
|
||||
Convert a DNS error code to a string.
|
||||
|
||||
@param err the DNS error code
|
||||
@return a string containing an explanation of the error code
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
const char *evdns_err_to_string(int err);
|
||||
|
||||
|
||||
/**
|
||||
Add a nameserver.
|
||||
|
||||
The address should be an IPv4 address in network byte order.
|
||||
The type of address is chosen so that it matches in_addr.s_addr.
|
||||
|
||||
@param base the evdns_base to which to add the name server
|
||||
@param address an IP address in network byte order
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
@see evdns_base_nameserver_ip_add()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_base_nameserver_add(struct evdns_base *base,
|
||||
unsigned long int address);
|
||||
|
||||
/**
|
||||
Get the number of configured nameservers.
|
||||
|
||||
This returns the number of configured nameservers (not necessarily the
|
||||
number of running nameservers). This is useful for double-checking
|
||||
whether our calls to the various nameserver configuration functions
|
||||
have been successful.
|
||||
|
||||
@param base the evdns_base to which to apply this operation
|
||||
@return the number of configured nameservers
|
||||
@see evdns_base_nameserver_add()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_base_count_nameservers(struct evdns_base *base);
|
||||
|
||||
/**
|
||||
Remove all configured nameservers, and suspend all pending resolves.
|
||||
|
||||
Resolves will not necessarily be re-attempted until evdns_base_resume() is called.
|
||||
|
||||
@param base the evdns_base to which to apply this operation
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
@see evdns_base_resume()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_base_clear_nameservers_and_suspend(struct evdns_base *base);
|
||||
|
||||
|
||||
/**
|
||||
Resume normal operation and continue any suspended resolve requests.
|
||||
|
||||
Re-attempt resolves left in limbo after an earlier call to
|
||||
evdns_base_clear_nameservers_and_suspend().
|
||||
|
||||
@param base the evdns_base to which to apply this operation
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
@see evdns_base_clear_nameservers_and_suspend()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_base_resume(struct evdns_base *base);
|
||||
|
||||
/**
|
||||
Add a nameserver by string address.
|
||||
|
||||
This function parses a n IPv4 or IPv6 address from a string and adds it as a
|
||||
nameserver. It supports the following formats:
|
||||
- [IPv6Address]:port
|
||||
- [IPv6Address]
|
||||
- IPv6Address
|
||||
- IPv4Address:port
|
||||
- IPv4Address
|
||||
|
||||
If no port is specified, it defaults to 53.
|
||||
|
||||
@param base the evdns_base to which to apply this operation
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
@see evdns_base_nameserver_add()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_base_nameserver_ip_add(struct evdns_base *base,
|
||||
const char *ip_as_string);
|
||||
|
||||
/**
|
||||
Add a nameserver by sockaddr.
|
||||
**/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int
|
||||
evdns_base_nameserver_sockaddr_add(struct evdns_base *base,
|
||||
const struct sockaddr *sa, ev_socklen_t len, unsigned flags);
|
||||
|
||||
struct evdns_request;
|
||||
|
||||
/**
|
||||
Lookup an A record for a given name.
|
||||
|
||||
@param base the evdns_base to which to apply this operation
|
||||
@param name a DNS hostname
|
||||
@param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query.
|
||||
@param callback a callback function to invoke when the request is completed
|
||||
@param ptr an argument to pass to the callback function
|
||||
@return an evdns_request object if successful, or NULL if an error occurred.
|
||||
@see evdns_resolve_ipv6(), evdns_resolve_reverse(), evdns_resolve_reverse_ipv6(), evdns_cancel_request()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
struct evdns_request *evdns_base_resolve_ipv4(struct evdns_base *base, const char *name, int flags, evdns_callback_type callback, void *ptr);
|
||||
|
||||
/**
|
||||
Lookup an AAAA record for a given name.
|
||||
|
||||
@param base the evdns_base to which to apply this operation
|
||||
@param name a DNS hostname
|
||||
@param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query.
|
||||
@param callback a callback function to invoke when the request is completed
|
||||
@param ptr an argument to pass to the callback function
|
||||
@return an evdns_request object if successful, or NULL if an error occurred.
|
||||
@see evdns_resolve_ipv4(), evdns_resolve_reverse(), evdns_resolve_reverse_ipv6(), evdns_cancel_request()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
struct evdns_request *evdns_base_resolve_ipv6(struct evdns_base *base, const char *name, int flags, evdns_callback_type callback, void *ptr);
|
||||
|
||||
struct in_addr;
|
||||
struct in6_addr;
|
||||
|
||||
/**
|
||||
Lookup a PTR record for a given IP address.
|
||||
|
||||
@param base the evdns_base to which to apply this operation
|
||||
@param in an IPv4 address
|
||||
@param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query.
|
||||
@param callback a callback function to invoke when the request is completed
|
||||
@param ptr an argument to pass to the callback function
|
||||
@return an evdns_request object if successful, or NULL if an error occurred.
|
||||
@see evdns_resolve_reverse_ipv6(), evdns_cancel_request()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
struct evdns_request *evdns_base_resolve_reverse(struct evdns_base *base, const struct in_addr *in, int flags, evdns_callback_type callback, void *ptr);
|
||||
|
||||
|
||||
/**
|
||||
Lookup a PTR record for a given IPv6 address.
|
||||
|
||||
@param base the evdns_base to which to apply this operation
|
||||
@param in an IPv6 address
|
||||
@param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query.
|
||||
@param callback a callback function to invoke when the request is completed
|
||||
@param ptr an argument to pass to the callback function
|
||||
@return an evdns_request object if successful, or NULL if an error occurred.
|
||||
@see evdns_resolve_reverse_ipv6(), evdns_cancel_request()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
struct evdns_request *evdns_base_resolve_reverse_ipv6(struct evdns_base *base, const struct in6_addr *in, int flags, evdns_callback_type callback, void *ptr);
|
||||
|
||||
/**
|
||||
Cancels a pending DNS resolution request.
|
||||
|
||||
@param base the evdns_base that was used to make the request
|
||||
@param req the evdns_request that was returned by calling a resolve function
|
||||
@see evdns_base_resolve_ipv4(), evdns_base_resolve_ipv6, evdns_base_resolve_reverse
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evdns_cancel_request(struct evdns_base *base, struct evdns_request *req);
|
||||
|
||||
/**
|
||||
Set the value of a configuration option.
|
||||
|
||||
The currently available configuration options are:
|
||||
|
||||
ndots, timeout, max-timeouts, max-inflight, attempts, randomize-case,
|
||||
bind-to, initial-probe-timeout, getaddrinfo-allow-skew,
|
||||
so-rcvbuf, so-sndbuf.
|
||||
|
||||
In versions before Libevent 2.0.3-alpha, the option name needed to end with
|
||||
a colon.
|
||||
|
||||
@param base the evdns_base to which to apply this operation
|
||||
@param option the name of the configuration option to be modified
|
||||
@param val the value to be set
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_base_set_option(struct evdns_base *base, const char *option, const char *val);
|
||||
|
||||
|
||||
/**
|
||||
Parse a resolv.conf file.
|
||||
|
||||
The 'flags' parameter determines what information is parsed from the
|
||||
resolv.conf file. See the man page for resolv.conf for the format of this
|
||||
file.
|
||||
|
||||
The following directives are not parsed from the file: sortlist, rotate,
|
||||
no-check-names, inet6, debug.
|
||||
|
||||
If this function encounters an error, the possible return values are: 1 =
|
||||
failed to open file, 2 = failed to stat file, 3 = file too large, 4 = out of
|
||||
memory, 5 = short read from file, 6 = no nameservers listed in the file
|
||||
|
||||
@param base the evdns_base to which to apply this operation
|
||||
@param flags any of DNS_OPTION_NAMESERVERS|DNS_OPTION_SEARCH|DNS_OPTION_MISC|
|
||||
DNS_OPTION_HOSTSFILE|DNS_OPTIONS_ALL|DNS_OPTION_NAMESERVERS_NO_DEFAULT
|
||||
@param filename the path to the resolv.conf file
|
||||
@return 0 if successful, or various positive error codes if an error
|
||||
occurred (see above)
|
||||
@see resolv.conf(3), evdns_config_windows_nameservers()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_base_resolv_conf_parse(struct evdns_base *base, int flags, const char *const filename);
|
||||
|
||||
/**
|
||||
Load an /etc/hosts-style file from 'hosts_fname' into 'base'.
|
||||
|
||||
If hosts_fname is NULL, add minimal entries for localhost, and nothing
|
||||
else.
|
||||
|
||||
Note that only evdns_getaddrinfo uses the /etc/hosts entries.
|
||||
|
||||
This function does not replace previously loaded hosts entries; to do that,
|
||||
call evdns_base_clear_host_addresses first.
|
||||
|
||||
Return 0 on success, negative on failure.
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_base_load_hosts(struct evdns_base *base, const char *hosts_fname);
|
||||
|
||||
#if defined(EVENT_IN_DOXYGEN_) || defined(_WIN32)
|
||||
/**
|
||||
Obtain nameserver information using the Windows API.
|
||||
|
||||
Attempt to configure a set of nameservers based on platform settings on
|
||||
a win32 host. Preferentially tries to use GetNetworkParams; if that fails,
|
||||
looks in the registry.
|
||||
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
@see evdns_resolv_conf_parse()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_base_config_windows_nameservers(struct evdns_base *);
|
||||
#define EVDNS_BASE_CONFIG_WINDOWS_NAMESERVERS_IMPLEMENTED
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
Clear the list of search domains.
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evdns_base_search_clear(struct evdns_base *base);
|
||||
|
||||
|
||||
/**
|
||||
Add a domain to the list of search domains
|
||||
|
||||
@param domain the domain to be added to the search list
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evdns_base_search_add(struct evdns_base *base, const char *domain);
|
||||
|
||||
|
||||
/**
|
||||
Set the 'ndots' parameter for searches.
|
||||
|
||||
Sets the number of dots which, when found in a name, causes
|
||||
the first query to be without any search domain.
|
||||
|
||||
@param ndots the new ndots parameter
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evdns_base_search_ndots_set(struct evdns_base *base, const int ndots);
|
||||
|
||||
/**
|
||||
A callback that is invoked when a log message is generated
|
||||
|
||||
@param is_warning indicates if the log message is a 'warning'
|
||||
@param msg the content of the log message
|
||||
*/
|
||||
typedef void (*evdns_debug_log_fn_type)(int is_warning, const char *msg);
|
||||
|
||||
|
||||
/**
|
||||
Set the callback function to handle DNS log messages. If this
|
||||
callback is not set, evdns log messages are handled with the regular
|
||||
Libevent logging system.
|
||||
|
||||
@param fn the callback to be invoked when a log message is generated
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evdns_set_log_fn(evdns_debug_log_fn_type fn);
|
||||
|
||||
/**
|
||||
Set a callback that will be invoked to generate transaction IDs. By
|
||||
default, we pick transaction IDs based on the current clock time, which
|
||||
is bad for security.
|
||||
|
||||
@param fn the new callback, or NULL to use the default.
|
||||
|
||||
NOTE: This function has no effect in Libevent 2.0.4-alpha and later,
|
||||
since Libevent now provides its own secure RNG.
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evdns_set_transaction_id_fn(ev_uint16_t (*fn)(void));
|
||||
|
||||
/**
|
||||
Set a callback used to generate random bytes. By default, we use
|
||||
the same function as passed to evdns_set_transaction_id_fn to generate
|
||||
bytes two at a time. If a function is provided here, it's also used
|
||||
to generate transaction IDs.
|
||||
|
||||
NOTE: This function has no effect in Libevent 2.0.4-alpha and later,
|
||||
since Libevent now provides its own secure RNG.
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evdns_set_random_bytes_fn(void (*fn)(char *, size_t));
|
||||
|
||||
/*
|
||||
* Functions used to implement a DNS server.
|
||||
*/
|
||||
|
||||
struct evdns_server_request;
|
||||
struct evdns_server_question;
|
||||
|
||||
/**
|
||||
A callback to implement a DNS server. The callback function receives a DNS
|
||||
request. It should then optionally add a number of answers to the reply
|
||||
using the evdns_server_request_add_*_reply functions, before calling either
|
||||
evdns_server_request_respond to send the reply back, or
|
||||
evdns_server_request_drop to decline to answer the request.
|
||||
|
||||
@param req A newly received request
|
||||
@param user_data A pointer that was passed to
|
||||
evdns_add_server_port_with_base().
|
||||
*/
|
||||
typedef void (*evdns_request_callback_fn_type)(struct evdns_server_request *, void *);
|
||||
#define EVDNS_ANSWER_SECTION 0
|
||||
#define EVDNS_AUTHORITY_SECTION 1
|
||||
#define EVDNS_ADDITIONAL_SECTION 2
|
||||
|
||||
#define EVDNS_TYPE_A 1
|
||||
#define EVDNS_TYPE_NS 2
|
||||
#define EVDNS_TYPE_CNAME 5
|
||||
#define EVDNS_TYPE_SOA 6
|
||||
#define EVDNS_TYPE_PTR 12
|
||||
#define EVDNS_TYPE_MX 15
|
||||
#define EVDNS_TYPE_TXT 16
|
||||
#define EVDNS_TYPE_AAAA 28
|
||||
|
||||
#define EVDNS_QTYPE_AXFR 252
|
||||
#define EVDNS_QTYPE_ALL 255
|
||||
|
||||
#define EVDNS_CLASS_INET 1
|
||||
|
||||
/* flags that can be set in answers; as part of the err parameter */
|
||||
#define EVDNS_FLAGS_AA 0x400
|
||||
#define EVDNS_FLAGS_RD 0x080
|
||||
|
||||
/** Create a new DNS server port.
|
||||
|
||||
@param base The event base to handle events for the server port.
|
||||
@param socket A UDP socket to accept DNS requests.
|
||||
@param flags Always 0 for now.
|
||||
@param callback A function to invoke whenever we get a DNS request
|
||||
on the socket.
|
||||
@param user_data Data to pass to the callback.
|
||||
@return an evdns_server_port structure for this server port or NULL if
|
||||
an error occurred.
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
struct evdns_server_port *evdns_add_server_port_with_base(struct event_base *base, evutil_socket_t socket, int flags, evdns_request_callback_fn_type callback, void *user_data);
|
||||
/** Close down a DNS server port, and free associated structures. */
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evdns_close_server_port(struct evdns_server_port *port);
|
||||
|
||||
/** Sets some flags in a reply we're building.
|
||||
Allows setting of the AA or RD flags
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evdns_server_request_set_flags(struct evdns_server_request *req, int flags);
|
||||
|
||||
/* Functions to add an answer to an in-progress DNS reply.
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_server_request_add_reply(struct evdns_server_request *req, int section, const char *name, int type, int dns_class, int ttl, int datalen, int is_name, const char *data);
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_server_request_add_a_reply(struct evdns_server_request *req, const char *name, int n, const void *addrs, int ttl);
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_server_request_add_aaaa_reply(struct evdns_server_request *req, const char *name, int n, const void *addrs, int ttl);
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_server_request_add_ptr_reply(struct evdns_server_request *req, struct in_addr *in, const char *inaddr_name, const char *hostname, int ttl);
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_server_request_add_cname_reply(struct evdns_server_request *req, const char *name, const char *cname, int ttl);
|
||||
|
||||
/**
|
||||
Send back a response to a DNS request, and free the request structure.
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_server_request_respond(struct evdns_server_request *req, int err);
|
||||
/**
|
||||
Free a DNS request without sending back a reply.
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_server_request_drop(struct evdns_server_request *req);
|
||||
struct sockaddr;
|
||||
/**
|
||||
Get the address that made a DNS request.
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_server_request_get_requesting_addr(struct evdns_server_request *req, struct sockaddr *sa, int addr_len);
|
||||
|
||||
/** Callback for evdns_getaddrinfo. */
|
||||
typedef void (*evdns_getaddrinfo_cb)(int result, struct evutil_addrinfo *res, void *arg);
|
||||
|
||||
struct evdns_base;
|
||||
struct evdns_getaddrinfo_request;
|
||||
/** Make a non-blocking getaddrinfo request using the dns_base in 'dns_base'.
|
||||
*
|
||||
* If we can answer the request immediately (with an error or not!), then we
|
||||
* invoke cb immediately and return NULL. Otherwise we return
|
||||
* an evdns_getaddrinfo_request and invoke cb later.
|
||||
*
|
||||
* When the callback is invoked, we pass as its first argument the error code
|
||||
* that getaddrinfo would return (or 0 for no error). As its second argument,
|
||||
* we pass the evutil_addrinfo structures we found (or NULL on error). We
|
||||
* pass 'arg' as the third argument.
|
||||
*
|
||||
* Limitations:
|
||||
*
|
||||
* - The AI_V4MAPPED and AI_ALL flags are not currently implemented.
|
||||
* - For ai_socktype, we only handle SOCKTYPE_STREAM, SOCKTYPE_UDP, and 0.
|
||||
* - For ai_protocol, we only handle IPPROTO_TCP, IPPROTO_UDP, and 0.
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
struct evdns_getaddrinfo_request *evdns_getaddrinfo(
|
||||
struct evdns_base *dns_base,
|
||||
const char *nodename, const char *servname,
|
||||
const struct evutil_addrinfo *hints_in,
|
||||
evdns_getaddrinfo_cb cb, void *arg);
|
||||
|
||||
/* Cancel an in-progress evdns_getaddrinfo. This MUST NOT be called after the
|
||||
* getaddrinfo's callback has been invoked. The resolves will be canceled,
|
||||
* and the callback will be invoked with the error EVUTIL_EAI_CANCEL. */
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evdns_getaddrinfo_cancel(struct evdns_getaddrinfo_request *req);
|
||||
|
||||
/**
|
||||
Retrieve the address of the 'idx'th configured nameserver.
|
||||
|
||||
@param base The evdns_base to examine.
|
||||
@param idx The index of the nameserver to get the address of.
|
||||
@param sa A location to receive the server's address.
|
||||
@param len The number of bytes available at sa.
|
||||
|
||||
@return the number of bytes written into sa on success. On failure, returns
|
||||
-1 if idx is greater than the number of configured nameservers, or a
|
||||
value greater than 'len' if len was not high enough.
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_base_get_nameserver_addr(struct evdns_base *base, int idx,
|
||||
struct sockaddr *sa, ev_socklen_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !EVENT2_DNS_H_INCLUDED_ */
|
||||
358
thirdparty/include/libevent/event2/dns_compat.h
vendored
Normal file
358
thirdparty/include/libevent/event2/dns_compat.h
vendored
Normal file
@@ -0,0 +1,358 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
#ifndef EVENT2_DNS_COMPAT_H_INCLUDED_
|
||||
#define EVENT2_DNS_COMPAT_H_INCLUDED_
|
||||
|
||||
/** @file event2/dns_compat.h
|
||||
|
||||
Potentially non-threadsafe versions of the functions in dns.h: provided
|
||||
only for backwards compatibility.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <event2/event-config.h>
|
||||
#ifdef EVENT__HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef EVENT__HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
/* For int types. */
|
||||
#include <event2/util.h>
|
||||
#include <event2/visibility.h>
|
||||
|
||||
/**
|
||||
Initialize the asynchronous DNS library.
|
||||
|
||||
This function initializes support for non-blocking name resolution by
|
||||
calling evdns_resolv_conf_parse() on UNIX and
|
||||
evdns_config_windows_nameservers() on Windows.
|
||||
|
||||
@deprecated This function is deprecated because it always uses the current
|
||||
event base, and is easily confused by multiple calls to event_init(), and
|
||||
so is not safe for multithreaded use. Additionally, it allocates a global
|
||||
structure that only one thread can use. The replacement is
|
||||
evdns_base_new().
|
||||
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
@see evdns_shutdown()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_init(void);
|
||||
|
||||
struct evdns_base;
|
||||
/**
|
||||
Return the global evdns_base created by event_init() and used by the other
|
||||
deprecated functions.
|
||||
|
||||
@deprecated This function is deprecated because use of the global
|
||||
evdns_base is error-prone.
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
struct evdns_base *evdns_get_global_base(void);
|
||||
|
||||
/**
|
||||
Shut down the asynchronous DNS resolver and terminate all active requests.
|
||||
|
||||
If the 'fail_requests' option is enabled, all active requests will return
|
||||
an empty result with the error flag set to DNS_ERR_SHUTDOWN. Otherwise,
|
||||
the requests will be silently discarded.
|
||||
|
||||
@deprecated This function is deprecated because it does not allow the
|
||||
caller to specify which evdns_base it applies to. The recommended
|
||||
function is evdns_base_shutdown().
|
||||
|
||||
@param fail_requests if zero, active requests will be aborted; if non-zero,
|
||||
active requests will return DNS_ERR_SHUTDOWN.
|
||||
@see evdns_init()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evdns_shutdown(int fail_requests);
|
||||
|
||||
/**
|
||||
Add a nameserver.
|
||||
|
||||
The address should be an IPv4 address in network byte order.
|
||||
The type of address is chosen so that it matches in_addr.s_addr.
|
||||
|
||||
@deprecated This function is deprecated because it does not allow the
|
||||
caller to specify which evdns_base it applies to. The recommended
|
||||
function is evdns_base_nameserver_add().
|
||||
|
||||
@param address an IP address in network byte order
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
@see evdns_nameserver_ip_add()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_nameserver_add(unsigned long int address);
|
||||
|
||||
/**
|
||||
Get the number of configured nameservers.
|
||||
|
||||
This returns the number of configured nameservers (not necessarily the
|
||||
number of running nameservers). This is useful for double-checking
|
||||
whether our calls to the various nameserver configuration functions
|
||||
have been successful.
|
||||
|
||||
@deprecated This function is deprecated because it does not allow the
|
||||
caller to specify which evdns_base it applies to. The recommended
|
||||
function is evdns_base_count_nameservers().
|
||||
|
||||
@return the number of configured nameservers
|
||||
@see evdns_nameserver_add()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_count_nameservers(void);
|
||||
|
||||
/**
|
||||
Remove all configured nameservers, and suspend all pending resolves.
|
||||
|
||||
Resolves will not necessarily be re-attempted until evdns_resume() is called.
|
||||
|
||||
@deprecated This function is deprecated because it does not allow the
|
||||
caller to specify which evdns_base it applies to. The recommended
|
||||
function is evdns_base_clear_nameservers_and_suspend().
|
||||
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
@see evdns_resume()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_clear_nameservers_and_suspend(void);
|
||||
|
||||
/**
|
||||
Resume normal operation and continue any suspended resolve requests.
|
||||
|
||||
Re-attempt resolves left in limbo after an earlier call to
|
||||
evdns_clear_nameservers_and_suspend().
|
||||
|
||||
@deprecated This function is deprecated because it does not allow the
|
||||
caller to specify which evdns_base it applies to. The recommended
|
||||
function is evdns_base_resume().
|
||||
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
@see evdns_clear_nameservers_and_suspend()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_resume(void);
|
||||
|
||||
/**
|
||||
Add a nameserver.
|
||||
|
||||
This wraps the evdns_nameserver_add() function by parsing a string as an IP
|
||||
address and adds it as a nameserver.
|
||||
|
||||
@deprecated This function is deprecated because it does not allow the
|
||||
caller to specify which evdns_base it applies to. The recommended
|
||||
function is evdns_base_nameserver_ip_add().
|
||||
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
@see evdns_nameserver_add()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_nameserver_ip_add(const char *ip_as_string);
|
||||
|
||||
/**
|
||||
Lookup an A record for a given name.
|
||||
|
||||
@deprecated This function is deprecated because it does not allow the
|
||||
caller to specify which evdns_base it applies to. The recommended
|
||||
function is evdns_base_resolve_ipv4().
|
||||
|
||||
@param name a DNS hostname
|
||||
@param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query.
|
||||
@param callback a callback function to invoke when the request is completed
|
||||
@param ptr an argument to pass to the callback function
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
@see evdns_resolve_ipv6(), evdns_resolve_reverse(), evdns_resolve_reverse_ipv6()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_resolve_ipv4(const char *name, int flags, evdns_callback_type callback, void *ptr);
|
||||
|
||||
/**
|
||||
Lookup an AAAA record for a given name.
|
||||
|
||||
@param name a DNS hostname
|
||||
@param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query.
|
||||
@param callback a callback function to invoke when the request is completed
|
||||
@param ptr an argument to pass to the callback function
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
@see evdns_resolve_ipv4(), evdns_resolve_reverse(), evdns_resolve_reverse_ipv6()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_resolve_ipv6(const char *name, int flags, evdns_callback_type callback, void *ptr);
|
||||
|
||||
struct in_addr;
|
||||
struct in6_addr;
|
||||
|
||||
/**
|
||||
Lookup a PTR record for a given IP address.
|
||||
|
||||
@deprecated This function is deprecated because it does not allow the
|
||||
caller to specify which evdns_base it applies to. The recommended
|
||||
function is evdns_base_resolve_reverse().
|
||||
|
||||
@param in an IPv4 address
|
||||
@param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query.
|
||||
@param callback a callback function to invoke when the request is completed
|
||||
@param ptr an argument to pass to the callback function
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
@see evdns_resolve_reverse_ipv6()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_resolve_reverse(const struct in_addr *in, int flags, evdns_callback_type callback, void *ptr);
|
||||
|
||||
/**
|
||||
Lookup a PTR record for a given IPv6 address.
|
||||
|
||||
@deprecated This function is deprecated because it does not allow the
|
||||
caller to specify which evdns_base it applies to. The recommended
|
||||
function is evdns_base_resolve_reverse_ipv6().
|
||||
|
||||
@param in an IPv6 address
|
||||
@param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query.
|
||||
@param callback a callback function to invoke when the request is completed
|
||||
@param ptr an argument to pass to the callback function
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
@see evdns_resolve_reverse_ipv6()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_resolve_reverse_ipv6(const struct in6_addr *in, int flags, evdns_callback_type callback, void *ptr);
|
||||
|
||||
/**
|
||||
Set the value of a configuration option.
|
||||
|
||||
The currently available configuration options are:
|
||||
|
||||
ndots, timeout, max-timeouts, max-inflight, and attempts
|
||||
|
||||
@deprecated This function is deprecated because it does not allow the
|
||||
caller to specify which evdns_base it applies to. The recommended
|
||||
function is evdns_base_set_option().
|
||||
|
||||
@param option the name of the configuration option to be modified
|
||||
@param val the value to be set
|
||||
@param flags Ignored.
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_set_option(const char *option, const char *val, int flags);
|
||||
|
||||
/**
|
||||
Parse a resolv.conf file.
|
||||
|
||||
The 'flags' parameter determines what information is parsed from the
|
||||
resolv.conf file. See the man page for resolv.conf for the format of this
|
||||
file.
|
||||
|
||||
The following directives are not parsed from the file: sortlist, rotate,
|
||||
no-check-names, inet6, debug.
|
||||
|
||||
If this function encounters an error, the possible return values are: 1 =
|
||||
failed to open file, 2 = failed to stat file, 3 = file too large, 4 = out of
|
||||
memory, 5 = short read from file, 6 = no nameservers listed in the file
|
||||
|
||||
@deprecated This function is deprecated because it does not allow the
|
||||
caller to specify which evdns_base it applies to. The recommended
|
||||
function is evdns_base_resolv_conf_parse().
|
||||
|
||||
@param flags any of DNS_OPTION_NAMESERVERS|DNS_OPTION_SEARCH|DNS_OPTION_MISC|
|
||||
DNS_OPTIONS_ALL
|
||||
@param filename the path to the resolv.conf file
|
||||
@return 0 if successful, or various positive error codes if an error
|
||||
occurred (see above)
|
||||
@see resolv.conf(3), evdns_config_windows_nameservers()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_resolv_conf_parse(int flags, const char *const filename);
|
||||
|
||||
/**
|
||||
Clear the list of search domains.
|
||||
|
||||
@deprecated This function is deprecated because it does not allow the
|
||||
caller to specify which evdns_base it applies to. The recommended
|
||||
function is evdns_base_search_clear().
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evdns_search_clear(void);
|
||||
|
||||
/**
|
||||
Add a domain to the list of search domains
|
||||
|
||||
@deprecated This function is deprecated because it does not allow the
|
||||
caller to specify which evdns_base it applies to. The recommended
|
||||
function is evdns_base_search_add().
|
||||
|
||||
@param domain the domain to be added to the search list
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evdns_search_add(const char *domain);
|
||||
|
||||
/**
|
||||
Set the 'ndots' parameter for searches.
|
||||
|
||||
Sets the number of dots which, when found in a name, causes
|
||||
the first query to be without any search domain.
|
||||
|
||||
@deprecated This function is deprecated because it does not allow the
|
||||
caller to specify which evdns_base it applies to. The recommended
|
||||
function is evdns_base_search_ndots_set().
|
||||
|
||||
@param ndots the new ndots parameter
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evdns_search_ndots_set(const int ndots);
|
||||
|
||||
/**
|
||||
As evdns_server_new_with_base.
|
||||
|
||||
@deprecated This function is deprecated because it does not allow the
|
||||
caller to specify which even_base it uses. The recommended
|
||||
function is evdns_add_server_port_with_base().
|
||||
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
struct evdns_server_port *
|
||||
evdns_add_server_port(evutil_socket_t socket, int flags,
|
||||
evdns_request_callback_fn_type callback, void *user_data);
|
||||
|
||||
#ifdef _WIN32
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evdns_config_windows_nameservers(void);
|
||||
#define EVDNS_CONFIG_WINDOWS_NAMESERVERS_IMPLEMENTED
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EVENT2_EVENT_COMPAT_H_INCLUDED_ */
|
||||
80
thirdparty/include/libevent/event2/dns_struct.h
vendored
Normal file
80
thirdparty/include/libevent/event2/dns_struct.h
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
#ifndef EVENT2_DNS_STRUCT_H_INCLUDED_
|
||||
#define EVENT2_DNS_STRUCT_H_INCLUDED_
|
||||
|
||||
/** @file event2/dns_struct.h
|
||||
|
||||
Data structures for dns. Using these structures may hurt forward
|
||||
compatibility with later versions of Libevent: be careful!
|
||||
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <event2/event-config.h>
|
||||
#ifdef EVENT__HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef EVENT__HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
/* For int types. */
|
||||
#include <event2/util.h>
|
||||
|
||||
/*
|
||||
* Structures used to implement a DNS server.
|
||||
*/
|
||||
|
||||
struct evdns_server_request {
|
||||
int flags;
|
||||
int nquestions;
|
||||
struct evdns_server_question **questions;
|
||||
};
|
||||
struct evdns_server_question {
|
||||
int type;
|
||||
#ifdef __cplusplus
|
||||
int dns_question_class;
|
||||
#else
|
||||
/* You should refer to this field as "dns_question_class". The
|
||||
* name "class" works in C for backward compatibility, and will be
|
||||
* removed in a future version. (1.5 or later). */
|
||||
int class;
|
||||
#define dns_question_class class
|
||||
#endif
|
||||
char name[1];
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EVENT2_DNS_STRUCT_H_INCLUDED_ */
|
||||
|
||||
630
thirdparty/include/libevent/event2/event-config.h
vendored
Normal file
630
thirdparty/include/libevent/event2/event-config.h
vendored
Normal file
@@ -0,0 +1,630 @@
|
||||
/* event2/event-config.h
|
||||
*
|
||||
* This file was generated by autoconf when libevent was built, and post-
|
||||
* processed by Libevent so that its macros would have a uniform prefix.
|
||||
*
|
||||
* DO NOT EDIT THIS FILE.
|
||||
*
|
||||
* Do not rely on macros in this file existing in later versions.
|
||||
*/
|
||||
|
||||
#ifndef EVENT2_EVENT_CONFIG_H_INCLUDED_
|
||||
#define EVENT2_EVENT_CONFIG_H_INCLUDED_
|
||||
|
||||
/* config.h. Generated from config.h.in by configure. */
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define if libevent should build without support for a debug mode */
|
||||
/* #undef EVENT__DISABLE_DEBUG_MODE */
|
||||
|
||||
/* Define if libevent should not allow replacing the mm functions */
|
||||
/* #undef EVENT__DISABLE_MM_REPLACEMENT */
|
||||
|
||||
/* Define if libevent should not be compiled with thread support */
|
||||
/* #undef EVENT__DISABLE_THREAD_SUPPORT */
|
||||
|
||||
/* Define to 1 if you have the `accept4' function. */
|
||||
#define EVENT__HAVE_ACCEPT4 1
|
||||
|
||||
/* Define to 1 if you have the <afunix.h> header file. */
|
||||
/* #undef EVENT__HAVE_AFUNIX_H */
|
||||
|
||||
/* Define to 1 if you have the `arc4random' function. */
|
||||
/* #undef EVENT__HAVE_ARC4RANDOM */
|
||||
|
||||
/* Define to 1 if you have the `arc4random_addrandom' function. */
|
||||
/* #undef EVENT__HAVE_ARC4RANDOM_ADDRANDOM */
|
||||
|
||||
/* Define to 1 if you have the `arc4random_buf' function. */
|
||||
/* #undef EVENT__HAVE_ARC4RANDOM_BUF */
|
||||
|
||||
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
||||
#define EVENT__HAVE_ARPA_INET_H 1
|
||||
|
||||
/* Define to 1 if you have the `clock_gettime' function. */
|
||||
#define EVENT__HAVE_CLOCK_GETTIME 1
|
||||
|
||||
/* Define to 1 if you have the declaration of `CTL_KERN', and to 0 if you
|
||||
don't. */
|
||||
/* #undef EVENT__HAVE_DECL_CTL_KERN */
|
||||
|
||||
/* Define to 1 if you have the declaration of `KERN_ARND', and to 0 if you
|
||||
don't. */
|
||||
/* #undef EVENT__HAVE_DECL_KERN_ARND */
|
||||
|
||||
/* Define if /dev/poll is available */
|
||||
/* #undef EVENT__HAVE_DEVPOLL */
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#define EVENT__HAVE_DLFCN_H 1
|
||||
|
||||
/* Define if your system supports the epoll system calls */
|
||||
#define EVENT__HAVE_EPOLL 1
|
||||
|
||||
/* Define to 1 if you have the `epoll_create1' function. */
|
||||
#define EVENT__HAVE_EPOLL_CREATE1 1
|
||||
|
||||
/* Define to 1 if you have the `epoll_ctl' function. */
|
||||
#define EVENT__HAVE_EPOLL_CTL 1
|
||||
|
||||
/* Define to 1 if you have the <errno.h> header file. */
|
||||
#define EVENT__HAVE_ERRNO_H 1
|
||||
|
||||
/* Define to 1 if you have the `eventfd' function. */
|
||||
#define EVENT__HAVE_EVENTFD 1
|
||||
|
||||
/* Define if your system supports event ports */
|
||||
/* #undef EVENT__HAVE_EVENT_PORTS */
|
||||
|
||||
/* Define to 1 if you have the `fcntl' function. */
|
||||
#define EVENT__HAVE_FCNTL 1
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#define EVENT__HAVE_FCNTL_H 1
|
||||
|
||||
/* Define to 1 if the system has the type `fd_mask'. */
|
||||
#define EVENT__HAVE_FD_MASK 1
|
||||
|
||||
/* Do we have getaddrinfo()? */
|
||||
#define EVENT__HAVE_GETADDRINFO 1
|
||||
|
||||
/* Define to 1 if you have the `getegid' function. */
|
||||
#define EVENT__HAVE_GETEGID 1
|
||||
|
||||
/* Define to 1 if you have the `geteuid' function. */
|
||||
#define EVENT__HAVE_GETEUID 1
|
||||
|
||||
/* Define this if you have any gethostbyname_r() */
|
||||
/* #undef EVENT__HAVE_GETHOSTBYNAME_R */
|
||||
|
||||
/* Define this if gethostbyname_r takes 3 arguments */
|
||||
/* #undef EVENT__HAVE_GETHOSTBYNAME_R_3_ARG */
|
||||
|
||||
/* Define this if gethostbyname_r takes 5 arguments */
|
||||
/* #undef EVENT__HAVE_GETHOSTBYNAME_R_5_ARG */
|
||||
|
||||
/* Define this if gethostbyname_r takes 6 arguments */
|
||||
/* #undef EVENT__HAVE_GETHOSTBYNAME_R_6_ARG */
|
||||
|
||||
/* Define to 1 if you have the `getifaddrs' function. */
|
||||
#define EVENT__HAVE_GETIFADDRS 1
|
||||
|
||||
/* Define to 1 if you have the `getnameinfo' function. */
|
||||
#define EVENT__HAVE_GETNAMEINFO 1
|
||||
|
||||
/* Define to 1 if you have the `getprotobynumber' function. */
|
||||
#define EVENT__HAVE_GETPROTOBYNUMBER 1
|
||||
|
||||
/* Define to 1 if you have the `getrandom' function. */
|
||||
#define EVENT__HAVE_GETRANDOM 1
|
||||
|
||||
/* Define to 1 if you have the `getservbyname' function. */
|
||||
#define EVENT__HAVE_GETSERVBYNAME 1
|
||||
|
||||
/* Define to 1 if you have the `gettimeofday' function. */
|
||||
#define EVENT__HAVE_GETTIMEOFDAY 1
|
||||
|
||||
/* Define to 1 if you have the <ifaddrs.h> header file. */
|
||||
#define EVENT__HAVE_IFADDRS_H 1
|
||||
|
||||
/* Define to 1 if you have the `inet_ntop' function. */
|
||||
#define EVENT__HAVE_INET_NTOP 1
|
||||
|
||||
/* Define to 1 if you have the `inet_pton' function. */
|
||||
#define EVENT__HAVE_INET_PTON 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define EVENT__HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the `issetugid' function. */
|
||||
/* #undef EVENT__HAVE_ISSETUGID */
|
||||
|
||||
/* Define to 1 if you have the `kqueue' function. */
|
||||
/* #undef EVENT__HAVE_KQUEUE */
|
||||
|
||||
/* Define to 1 if you have the `ws2_32' library (-lws2_32). */
|
||||
/* #undef EVENT__HAVE_LIBWS2_32 */
|
||||
|
||||
/* Define if the system has zlib */
|
||||
/* #undef EVENT__HAVE_LIBZ */
|
||||
|
||||
/* Define to 1 if you have the `mach_absolute_time' function. */
|
||||
/* #undef EVENT__HAVE_MACH_ABSOLUTE_TIME */
|
||||
|
||||
/* Define to 1 if you have the <mach/mach.h> header file. */
|
||||
/* #undef EVENT__HAVE_MACH_MACH_H */
|
||||
|
||||
/* Define to 1 if you have the <mach/mach_time.h> header file. */
|
||||
/* #undef EVENT__HAVE_MACH_MACH_TIME_H */
|
||||
|
||||
/* Define to 1 if you have the <minix/config.h> header file. */
|
||||
/* #undef EVENT__HAVE_MINIX_CONFIG_H */
|
||||
|
||||
/* Define to 1 if you have the `mmap' function. */
|
||||
#define EVENT__HAVE_MMAP 1
|
||||
|
||||
/* Define to 1 if you have the `nanosleep' function. */
|
||||
#define EVENT__HAVE_NANOSLEEP 1
|
||||
|
||||
/* Define to 1 if you have the <netdb.h> header file. */
|
||||
#define EVENT__HAVE_NETDB_H 1
|
||||
|
||||
/* Define to 1 if you have the <netinet/in6.h> header file. */
|
||||
/* #undef EVENT__HAVE_NETINET_IN6_H */
|
||||
|
||||
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||
#define EVENT__HAVE_NETINET_IN_H 1
|
||||
|
||||
/* Define to 1 if you have the <netinet/tcp.h> header file. */
|
||||
#define EVENT__HAVE_NETINET_TCP_H 1
|
||||
|
||||
/* Define if the system has openssl */
|
||||
#define EVENT__HAVE_OPENSSL 1
|
||||
|
||||
/* Define to 1 if you have the <openssl/ssl.h> header file. */
|
||||
#define EVENT__HAVE_OPENSSL_SSL_H 1
|
||||
|
||||
/* Define to 1 if you have the `pipe' function. */
|
||||
#define EVENT__HAVE_PIPE 1
|
||||
|
||||
/* Define to 1 if you have the `pipe2' function. */
|
||||
#define EVENT__HAVE_PIPE2 1
|
||||
|
||||
/* Define to 1 if you have the `poll' function. */
|
||||
#define EVENT__HAVE_POLL 1
|
||||
|
||||
/* Define to 1 if you have the <poll.h> header file. */
|
||||
#define EVENT__HAVE_POLL_H 1
|
||||
|
||||
/* Define to 1 if you have the `port_create' function. */
|
||||
/* #undef EVENT__HAVE_PORT_CREATE */
|
||||
|
||||
/* Define to 1 if you have the <port.h> header file. */
|
||||
/* #undef EVENT__HAVE_PORT_H */
|
||||
|
||||
/* Define if you have POSIX threads libraries and header files. */
|
||||
/* #undef EVENT__HAVE_PTHREAD */
|
||||
|
||||
/* Define if we have pthreads on this system */
|
||||
#define EVENT__HAVE_PTHREADS 1
|
||||
|
||||
/* Define to 1 if you have the `putenv' function. */
|
||||
#define EVENT__HAVE_PUTENV 1
|
||||
|
||||
/* Define to 1 if the system has the type `sa_family_t'. */
|
||||
#define EVENT__HAVE_SA_FAMILY_T 1
|
||||
|
||||
/* Define to 1 if you have the `select' function. */
|
||||
#define EVENT__HAVE_SELECT 1
|
||||
|
||||
/* Define to 1 if you have the `sendfile' function. */
|
||||
#define EVENT__HAVE_SENDFILE 1
|
||||
|
||||
/* Define to 1 if you have the `setenv' function. */
|
||||
#define EVENT__HAVE_SETENV 1
|
||||
|
||||
/* Define if F_SETFD is defined in <fcntl.h> */
|
||||
#define EVENT__HAVE_SETFD 1
|
||||
|
||||
/* Define to 1 if you have the `setrlimit' function. */
|
||||
#define EVENT__HAVE_SETRLIMIT 1
|
||||
|
||||
/* Define to 1 if you have the `sigaction' function. */
|
||||
#define EVENT__HAVE_SIGACTION 1
|
||||
|
||||
/* Define to 1 if you have the `signal' function. */
|
||||
#define EVENT__HAVE_SIGNAL 1
|
||||
|
||||
/* Define to 1 if you have the `splice' function. */
|
||||
#define EVENT__HAVE_SPLICE 1
|
||||
|
||||
/* Define to 1 if you have the <stdarg.h> header file. */
|
||||
#define EVENT__HAVE_STDARG_H 1
|
||||
|
||||
/* Define to 1 if you have the <stddef.h> header file. */
|
||||
#define EVENT__HAVE_STDDEF_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define EVENT__HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdio.h> header file. */
|
||||
#define EVENT__HAVE_STDIO_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define EVENT__HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define EVENT__HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define EVENT__HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the `strlcpy' function. */
|
||||
/* #undef EVENT__HAVE_STRLCPY */
|
||||
|
||||
/* Define to 1 if you have the `strsep' function. */
|
||||
#define EVENT__HAVE_STRSEP 1
|
||||
|
||||
/* Define to 1 if you have the `strtok_r' function. */
|
||||
#define EVENT__HAVE_STRTOK_R 1
|
||||
|
||||
/* Define to 1 if you have the `strtoll' function. */
|
||||
#define EVENT__HAVE_STRTOLL 1
|
||||
|
||||
/* Define to 1 if the system has the type `struct addrinfo'. */
|
||||
#define EVENT__HAVE_STRUCT_ADDRINFO 1
|
||||
|
||||
/* Define to 1 if the system has the type `struct in6_addr'. */
|
||||
#define EVENT__HAVE_STRUCT_IN6_ADDR 1
|
||||
|
||||
/* Define to 1 if `s6_addr16' is a member of `struct in6_addr'. */
|
||||
#define EVENT__HAVE_STRUCT_IN6_ADDR_S6_ADDR16 1
|
||||
|
||||
/* Define to 1 if `s6_addr32' is a member of `struct in6_addr'. */
|
||||
#define EVENT__HAVE_STRUCT_IN6_ADDR_S6_ADDR32 1
|
||||
|
||||
/* Define to 1 if the system has the type `struct linger'. */
|
||||
#define EVENT__HAVE_STRUCT_LINGER 1
|
||||
|
||||
/* Define to 1 if the system has the type `struct sockaddr_in6'. */
|
||||
#define EVENT__HAVE_STRUCT_SOCKADDR_IN6 1
|
||||
|
||||
/* Define to 1 if `sin6_len' is a member of `struct sockaddr_in6'. */
|
||||
/* #undef EVENT__HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN */
|
||||
|
||||
/* Define to 1 if `sin_len' is a member of `struct sockaddr_in'. */
|
||||
/* #undef EVENT__HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
|
||||
|
||||
/* Define to 1 if the system has the type `struct sockaddr_storage'. */
|
||||
#define EVENT__HAVE_STRUCT_SOCKADDR_STORAGE 1
|
||||
|
||||
/* Define to 1 if `ss_family' is a member of `struct sockaddr_storage'. */
|
||||
#define EVENT__HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY 1
|
||||
|
||||
/* Define to 1 if `__ss_family' is a member of `struct sockaddr_storage'. */
|
||||
/* #undef EVENT__HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY */
|
||||
|
||||
/* Define to 1 if the system has the type `struct sockaddr_un'. */
|
||||
#define EVENT__HAVE_STRUCT_SOCKADDR_UN 1
|
||||
|
||||
/* Define to 1 if you have the `sysctl' function. */
|
||||
/* #undef EVENT__HAVE_SYSCTL */
|
||||
|
||||
/* Define to 1 if you have the <sys/devpoll.h> header file. */
|
||||
/* #undef EVENT__HAVE_SYS_DEVPOLL_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/epoll.h> header file. */
|
||||
#define EVENT__HAVE_SYS_EPOLL_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/eventfd.h> header file. */
|
||||
#define EVENT__HAVE_SYS_EVENTFD_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/event.h> header file. */
|
||||
/* #undef EVENT__HAVE_SYS_EVENT_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
||||
#define EVENT__HAVE_SYS_IOCTL_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/mman.h> header file. */
|
||||
#define EVENT__HAVE_SYS_MMAN_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||
#define EVENT__HAVE_SYS_PARAM_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/queue.h> header file. */
|
||||
#define EVENT__HAVE_SYS_QUEUE_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/random.h> header file. */
|
||||
#define EVENT__HAVE_SYS_RANDOM_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/resource.h> header file. */
|
||||
#define EVENT__HAVE_SYS_RESOURCE_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/select.h> header file. */
|
||||
#define EVENT__HAVE_SYS_SELECT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/sendfile.h> header file. */
|
||||
#define EVENT__HAVE_SYS_SENDFILE_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||
#define EVENT__HAVE_SYS_SOCKET_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define EVENT__HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/sysctl.h> header file. */
|
||||
/* #undef EVENT__HAVE_SYS_SYSCTL_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/timerfd.h> header file. */
|
||||
#define EVENT__HAVE_SYS_TIMERFD_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
#define EVENT__HAVE_SYS_TIME_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define EVENT__HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/uio.h> header file. */
|
||||
#define EVENT__HAVE_SYS_UIO_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/un.h> header file. */
|
||||
#define EVENT__HAVE_SYS_UN_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/wait.h> header file. */
|
||||
#define EVENT__HAVE_SYS_WAIT_H 1
|
||||
|
||||
/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */
|
||||
#define EVENT__HAVE_TAILQFOREACH 1
|
||||
|
||||
/* Define if timeradd is defined in <sys/time.h> */
|
||||
#define EVENT__HAVE_TIMERADD 1
|
||||
|
||||
/* Define if timerclear is defined in <sys/time.h> */
|
||||
#define EVENT__HAVE_TIMERCLEAR 1
|
||||
|
||||
/* Define if timercmp is defined in <sys/time.h> */
|
||||
#define EVENT__HAVE_TIMERCMP 1
|
||||
|
||||
/* Define to 1 if you have the `timerfd_create' function. */
|
||||
#define EVENT__HAVE_TIMERFD_CREATE 1
|
||||
|
||||
/* Define if timerisset is defined in <sys/time.h> */
|
||||
#define EVENT__HAVE_TIMERISSET 1
|
||||
|
||||
/* Define to 1 if the system has the type `uint16_t'. */
|
||||
#define EVENT__HAVE_UINT16_T 1
|
||||
|
||||
/* Define to 1 if the system has the type `uint32_t'. */
|
||||
#define EVENT__HAVE_UINT32_T 1
|
||||
|
||||
/* Define to 1 if the system has the type `uint64_t'. */
|
||||
#define EVENT__HAVE_UINT64_T 1
|
||||
|
||||
/* Define to 1 if the system has the type `uint8_t'. */
|
||||
#define EVENT__HAVE_UINT8_T 1
|
||||
|
||||
/* Define to 1 if the system has the type `uintptr_t'. */
|
||||
#define EVENT__HAVE_UINTPTR_T 1
|
||||
|
||||
/* Define to 1 if you have the `umask' function. */
|
||||
#define EVENT__HAVE_UMASK 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define EVENT__HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to 1 if you have the `unsetenv' function. */
|
||||
#define EVENT__HAVE_UNSETENV 1
|
||||
|
||||
/* Define to 1 if you have the `usleep' function. */
|
||||
#define EVENT__HAVE_USLEEP 1
|
||||
|
||||
/* Define to 1 if you have the `vasprintf' function. */
|
||||
#define EVENT__HAVE_VASPRINTF 1
|
||||
|
||||
/* Define to 1 if you have the <wchar.h> header file. */
|
||||
#define EVENT__HAVE_WCHAR_H 1
|
||||
|
||||
/* Define if kqueue works correctly with pipes */
|
||||
/* #undef EVENT__HAVE_WORKING_KQUEUE */
|
||||
|
||||
/* Define to 1 if you have the <zlib.h> header file. */
|
||||
/* #undef EVENT__HAVE_ZLIB_H */
|
||||
|
||||
/* Define to 1 if you have the `_gmtime64' function. */
|
||||
/* #undef EVENT__HAVE__GMTIME64 */
|
||||
|
||||
/* Define to 1 if you have the `_gmtime64_s' function. */
|
||||
/* #undef EVENT__HAVE__GMTIME64_S */
|
||||
|
||||
/* Define to 1 if compiler have __FUNCTION__ */
|
||||
#define EVENT__HAVE___FUNCTION__ 1
|
||||
|
||||
/* Define to 1 if compiler have __func__ */
|
||||
#define EVENT__HAVE___func__ 1
|
||||
|
||||
/* Define to the sub-directory where libtool stores uninstalled libraries. */
|
||||
#define EVENT__LT_OBJDIR ".libs/"
|
||||
|
||||
/* Numeric representation of the version */
|
||||
#define EVENT__NUMERIC_VERSION 0x02010c00
|
||||
|
||||
/* Name of package */
|
||||
#define EVENT__PACKAGE "libevent"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define EVENT__PACKAGE_BUGREPORT ""
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define EVENT__PACKAGE_NAME "libevent"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define EVENT__PACKAGE_STRING "libevent 2.1.12-stable"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define EVENT__PACKAGE_TARNAME "libevent"
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#define EVENT__PACKAGE_URL ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define EVENT__PACKAGE_VERSION "2.1.12-stable"
|
||||
|
||||
/* Define to necessary symbol if this constant uses a non-standard name on
|
||||
your system. */
|
||||
/* #undef EVENT__PTHREAD_CREATE_JOINABLE */
|
||||
|
||||
/* The size of `int', as computed by sizeof. */
|
||||
#define EVENT__SIZEOF_INT 4
|
||||
|
||||
/* The size of `long', as computed by sizeof. */
|
||||
#define EVENT__SIZEOF_LONG 8
|
||||
|
||||
/* The size of `long long', as computed by sizeof. */
|
||||
#define EVENT__SIZEOF_LONG_LONG 8
|
||||
|
||||
/* The size of `off_t', as computed by sizeof. */
|
||||
#define EVENT__SIZEOF_OFF_T 8
|
||||
|
||||
/* The size of `pthread_t', as computed by sizeof. */
|
||||
#define EVENT__SIZEOF_PTHREAD_T 8
|
||||
|
||||
/* The size of `short', as computed by sizeof. */
|
||||
#define EVENT__SIZEOF_SHORT 2
|
||||
|
||||
/* The size of `size_t', as computed by sizeof. */
|
||||
#define EVENT__SIZEOF_SIZE_T 8
|
||||
|
||||
/* The size of `time_t', as computed by sizeof. */
|
||||
#define EVENT__SIZEOF_TIME_T 8
|
||||
|
||||
/* The size of `void *', as computed by sizeof. */
|
||||
#define EVENT__SIZEOF_VOID_P 8
|
||||
|
||||
/* Define to 1 if all of the C90 standard headers exist (not just the ones
|
||||
required in a freestanding environment). This macro is provided for
|
||||
backward compatibility; new code need not use it. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. This
|
||||
macro is obsolete. */
|
||||
#define EVENT__TIME_WITH_SYS_TIME 1
|
||||
|
||||
/* Enable extensions on AIX 3, Interix. */
|
||||
#ifndef _ALL_SOURCE
|
||||
# define _ALL_SOURCE 1
|
||||
#endif
|
||||
/* Enable general extensions on macOS. */
|
||||
#ifndef _DARWIN_C_SOURCE
|
||||
# define _DARWIN_C_SOURCE 1
|
||||
#endif
|
||||
/* Enable general extensions on Solaris. */
|
||||
#ifndef __EXTENSIONS__
|
||||
# define __EXTENSIONS__ 1
|
||||
#endif
|
||||
/* Enable GNU extensions on systems that have them. */
|
||||
#ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE 1
|
||||
#endif
|
||||
/* Enable X/Open compliant socket functions that do not require linking
|
||||
with -lxnet on HP-UX 11.11. */
|
||||
#ifndef _HPUX_ALT_XOPEN_SOCKET_API
|
||||
# define _HPUX_ALT_XOPEN_SOCKET_API 1
|
||||
#endif
|
||||
/* Identify the host operating system as Minix.
|
||||
This macro does not affect the system headers' behavior.
|
||||
A future release of Autoconf may stop defining this macro. */
|
||||
#ifndef _MINIX
|
||||
/* # undef _MINIX */
|
||||
#endif
|
||||
/* Enable general extensions on NetBSD.
|
||||
Enable NetBSD compatibility extensions on Minix. */
|
||||
#ifndef _NETBSD_SOURCE
|
||||
# define _NETBSD_SOURCE 1
|
||||
#endif
|
||||
/* Enable OpenBSD compatibility extensions on NetBSD.
|
||||
Oddly enough, this does nothing on OpenBSD. */
|
||||
#ifndef _OPENBSD_SOURCE
|
||||
# define _OPENBSD_SOURCE 1
|
||||
#endif
|
||||
/* Define to 1 if needed for POSIX-compatible behavior. */
|
||||
#ifndef _POSIX_SOURCE
|
||||
/* # undef _POSIX_SOURCE */
|
||||
#endif
|
||||
/* Define to 2 if needed for POSIX-compatible behavior. */
|
||||
#ifndef _POSIX_1_SOURCE
|
||||
/* # undef _POSIX_1_SOURCE */
|
||||
#endif
|
||||
/* Enable POSIX-compatible threading on Solaris. */
|
||||
#ifndef _POSIX_PTHREAD_SEMANTICS
|
||||
# define _POSIX_PTHREAD_SEMANTICS 1
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-5:2014. */
|
||||
#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
|
||||
# define __STDC_WANT_IEC_60559_ATTRIBS_EXT__ 1
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-1:2014. */
|
||||
#ifndef __STDC_WANT_IEC_60559_BFP_EXT__
|
||||
# define __STDC_WANT_IEC_60559_BFP_EXT__ 1
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-2:2015. */
|
||||
#ifndef __STDC_WANT_IEC_60559_DFP_EXT__
|
||||
# define __STDC_WANT_IEC_60559_DFP_EXT__ 1
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */
|
||||
#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__
|
||||
# define __STDC_WANT_IEC_60559_FUNCS_EXT__ 1
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */
|
||||
#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
|
||||
# define __STDC_WANT_IEC_60559_TYPES_EXT__ 1
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TR 24731-2:2010. */
|
||||
#ifndef __STDC_WANT_LIB_EXT2__
|
||||
# define __STDC_WANT_LIB_EXT2__ 1
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC 24747:2009. */
|
||||
#ifndef __STDC_WANT_MATH_SPEC_FUNCS__
|
||||
# define __STDC_WANT_MATH_SPEC_FUNCS__ 1
|
||||
#endif
|
||||
/* Enable extensions on HP NonStop. */
|
||||
#ifndef _TANDEM_SOURCE
|
||||
# define _TANDEM_SOURCE 1
|
||||
#endif
|
||||
/* Enable X/Open extensions. Define to 500 only if necessary
|
||||
to make mbstate_t available. */
|
||||
#ifndef _XOPEN_SOURCE
|
||||
/* # undef _XOPEN_SOURCE */
|
||||
#endif
|
||||
|
||||
|
||||
/* Version number of package */
|
||||
#define EVENT__VERSION "2.1.12-stable"
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
/* #undef _FILE_OFFSET_BITS */
|
||||
|
||||
/* Define for large files, on AIX-style hosts. */
|
||||
/* #undef _LARGE_FILES */
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
/* #undef const */
|
||||
|
||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||
#ifndef __cplusplus
|
||||
/* #undef inline */
|
||||
#endif
|
||||
|
||||
/* Define as a signed integer type capable of holding a process identifier. */
|
||||
/* #undef pid_t */
|
||||
|
||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||
/* #undef size_t */
|
||||
|
||||
/* Define to unsigned int if you dont have it */
|
||||
/* #undef socklen_t */
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
/* #undef ssize_t */
|
||||
|
||||
#endif /* event2/event-config.h */
|
||||
1672
thirdparty/include/libevent/event2/event.h
vendored
Normal file
1672
thirdparty/include/libevent/event2/event.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
230
thirdparty/include/libevent/event2/event_compat.h
vendored
Normal file
230
thirdparty/include/libevent/event2/event_compat.h
vendored
Normal file
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
#ifndef EVENT2_EVENT_COMPAT_H_INCLUDED_
|
||||
#define EVENT2_EVENT_COMPAT_H_INCLUDED_
|
||||
|
||||
/** @file event2/event_compat.h
|
||||
|
||||
Potentially non-threadsafe versions of the functions in event.h: provided
|
||||
only for backwards compatibility.
|
||||
|
||||
In the oldest versions of Libevent, event_base was not a first-class
|
||||
structure. Instead, there was a single event base that every function
|
||||
manipulated. Later, when separate event bases were added, the old functions
|
||||
that didn't take an event_base argument needed to work by manipulating the
|
||||
"current" event base. This could lead to thread-safety issues, and obscure,
|
||||
hard-to-diagnose bugs.
|
||||
|
||||
@deprecated All functions in this file are by definition deprecated.
|
||||
*/
|
||||
#include <event2/visibility.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <event2/event-config.h>
|
||||
#ifdef EVENT__HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef EVENT__HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
/* For int types. */
|
||||
#include <event2/util.h>
|
||||
|
||||
/**
|
||||
Initialize the event API.
|
||||
|
||||
The event API needs to be initialized with event_init() before it can be
|
||||
used. Sets the global current base that gets used for events that have no
|
||||
base associated with them.
|
||||
|
||||
@deprecated This function is deprecated because it replaces the "current"
|
||||
event_base, and is totally unsafe for multithreaded use. The replacement
|
||||
is event_base_new().
|
||||
|
||||
@see event_base_set(), event_base_new()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
struct event_base *event_init(void);
|
||||
|
||||
/**
|
||||
Loop to process events.
|
||||
|
||||
Like event_base_dispatch(), but uses the "current" base.
|
||||
|
||||
@deprecated This function is deprecated because it is easily confused by
|
||||
multiple calls to event_init(), and because it is not safe for
|
||||
multithreaded use. The replacement is event_base_dispatch().
|
||||
|
||||
@see event_base_dispatch(), event_init()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int event_dispatch(void);
|
||||
|
||||
/**
|
||||
Handle events.
|
||||
|
||||
This function behaves like event_base_loop(), but uses the "current" base
|
||||
|
||||
@deprecated This function is deprecated because it uses the event base from
|
||||
the last call to event_init, and is therefore not safe for multithreaded
|
||||
use. The replacement is event_base_loop().
|
||||
|
||||
@see event_base_loop(), event_init()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int event_loop(int);
|
||||
|
||||
|
||||
/**
|
||||
Exit the event loop after the specified time.
|
||||
|
||||
This function behaves like event_base_loopexit(), except that it uses the
|
||||
"current" base.
|
||||
|
||||
@deprecated This function is deprecated because it uses the event base from
|
||||
the last call to event_init, and is therefore not safe for multithreaded
|
||||
use. The replacement is event_base_loopexit().
|
||||
|
||||
@see event_init, event_base_loopexit()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int event_loopexit(const struct timeval *);
|
||||
|
||||
|
||||
/**
|
||||
Abort the active event_loop() immediately.
|
||||
|
||||
This function behaves like event_base_loopbreakt(), except that it uses the
|
||||
"current" base.
|
||||
|
||||
@deprecated This function is deprecated because it uses the event base from
|
||||
the last call to event_init, and is therefore not safe for multithreaded
|
||||
use. The replacement is event_base_loopbreak().
|
||||
|
||||
@see event_base_loopbreak(), event_init()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int event_loopbreak(void);
|
||||
|
||||
/**
|
||||
Schedule a one-time event to occur.
|
||||
|
||||
@deprecated This function is obsolete, and has been replaced by
|
||||
event_base_once(). Its use is deprecated because it relies on the
|
||||
"current" base configured by event_init().
|
||||
|
||||
@see event_base_once()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int event_once(evutil_socket_t , short,
|
||||
void (*)(evutil_socket_t, short, void *), void *, const struct timeval *);
|
||||
|
||||
|
||||
/**
|
||||
Get the kernel event notification mechanism used by Libevent.
|
||||
|
||||
@deprecated This function is obsolete, and has been replaced by
|
||||
event_base_get_method(). Its use is deprecated because it relies on the
|
||||
"current" base configured by event_init().
|
||||
|
||||
@see event_base_get_method()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
const char *event_get_method(void);
|
||||
|
||||
|
||||
/**
|
||||
Set the number of different event priorities.
|
||||
|
||||
@deprecated This function is deprecated because it is easily confused by
|
||||
multiple calls to event_init(), and because it is not safe for
|
||||
multithreaded use. The replacement is event_base_priority_init().
|
||||
|
||||
@see event_base_priority_init()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int event_priority_init(int);
|
||||
|
||||
/**
|
||||
Prepare an event structure to be added.
|
||||
|
||||
@deprecated event_set() is not recommended for new code, because it requires
|
||||
a subsequent call to event_base_set() to be safe under most circumstances.
|
||||
Use event_assign() or event_new() instead.
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void event_set(struct event *, evutil_socket_t, short, void (*)(evutil_socket_t, short, void *), void *);
|
||||
|
||||
#define evtimer_set(ev, cb, arg) event_set((ev), -1, 0, (cb), (arg))
|
||||
#define evsignal_set(ev, x, cb, arg) \
|
||||
event_set((ev), (x), EV_SIGNAL|EV_PERSIST, (cb), (arg))
|
||||
|
||||
|
||||
/**
|
||||
@name timeout_* macros
|
||||
|
||||
@deprecated These macros are deprecated because their naming is inconsistent
|
||||
with the rest of Libevent. Use the evtimer_* macros instead.
|
||||
@{
|
||||
*/
|
||||
#define timeout_add(ev, tv) event_add((ev), (tv))
|
||||
#define timeout_set(ev, cb, arg) event_set((ev), -1, 0, (cb), (arg))
|
||||
#define timeout_del(ev) event_del(ev)
|
||||
#define timeout_pending(ev, tv) event_pending((ev), EV_TIMEOUT, (tv))
|
||||
#define timeout_initialized(ev) event_initialized(ev)
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
@name signal_* macros
|
||||
|
||||
@deprecated These macros are deprecated because their naming is inconsistent
|
||||
with the rest of Libevent. Use the evsignal_* macros instead.
|
||||
@{
|
||||
*/
|
||||
#define signal_add(ev, tv) event_add((ev), (tv))
|
||||
#define signal_set(ev, x, cb, arg) \
|
||||
event_set((ev), (x), EV_SIGNAL|EV_PERSIST, (cb), (arg))
|
||||
#define signal_del(ev) event_del(ev)
|
||||
#define signal_pending(ev, tv) event_pending((ev), EV_SIGNAL, (tv))
|
||||
#define signal_initialized(ev) event_initialized(ev)
|
||||
/**@}*/
|
||||
|
||||
#ifndef EVENT_FD
|
||||
/* These macros are obsolete; use event_get_fd and event_get_signal instead. */
|
||||
#define EVENT_FD(ev) ((int)event_get_fd(ev))
|
||||
#define EVENT_SIGNAL(ev) event_get_signal(ev)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EVENT2_EVENT_COMPAT_H_INCLUDED_ */
|
||||
180
thirdparty/include/libevent/event2/event_struct.h
vendored
Normal file
180
thirdparty/include/libevent/event2/event_struct.h
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
#ifndef EVENT2_EVENT_STRUCT_H_INCLUDED_
|
||||
#define EVENT2_EVENT_STRUCT_H_INCLUDED_
|
||||
|
||||
/** @file event2/event_struct.h
|
||||
|
||||
Structures used by event.h. Using these structures directly WILL harm
|
||||
forward compatibility: be careful.
|
||||
|
||||
No field declared in this file should be used directly in user code. Except
|
||||
for historical reasons, these fields would not be exposed at all.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <event2/event-config.h>
|
||||
#ifdef EVENT__HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef EVENT__HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
/* For int types. */
|
||||
#include <event2/util.h>
|
||||
|
||||
/* For evkeyvalq */
|
||||
#include <event2/keyvalq_struct.h>
|
||||
|
||||
#define EVLIST_TIMEOUT 0x01
|
||||
#define EVLIST_INSERTED 0x02
|
||||
#define EVLIST_SIGNAL 0x04
|
||||
#define EVLIST_ACTIVE 0x08
|
||||
#define EVLIST_INTERNAL 0x10
|
||||
#define EVLIST_ACTIVE_LATER 0x20
|
||||
#define EVLIST_FINALIZING 0x40
|
||||
#define EVLIST_INIT 0x80
|
||||
|
||||
#define EVLIST_ALL 0xff
|
||||
|
||||
/* Fix so that people don't have to run with <sys/queue.h> */
|
||||
#ifndef TAILQ_ENTRY
|
||||
#define EVENT_DEFINED_TQENTRY_
|
||||
#define TAILQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *tqe_next; /* next element */ \
|
||||
struct type **tqe_prev; /* address of previous next element */ \
|
||||
}
|
||||
#endif /* !TAILQ_ENTRY */
|
||||
|
||||
#ifndef TAILQ_HEAD
|
||||
#define EVENT_DEFINED_TQHEAD_
|
||||
#define TAILQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *tqh_first; \
|
||||
struct type **tqh_last; \
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Fix so that people don't have to run with <sys/queue.h> */
|
||||
#ifndef LIST_ENTRY
|
||||
#define EVENT_DEFINED_LISTENTRY_
|
||||
#define LIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *le_next; /* next element */ \
|
||||
struct type **le_prev; /* address of previous next element */ \
|
||||
}
|
||||
#endif /* !LIST_ENTRY */
|
||||
|
||||
#ifndef LIST_HEAD
|
||||
#define EVENT_DEFINED_LISTHEAD_
|
||||
#define LIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *lh_first; /* first element */ \
|
||||
}
|
||||
#endif /* !LIST_HEAD */
|
||||
|
||||
struct event;
|
||||
|
||||
struct event_callback {
|
||||
TAILQ_ENTRY(event_callback) evcb_active_next;
|
||||
short evcb_flags;
|
||||
ev_uint8_t evcb_pri; /* smaller numbers are higher priority */
|
||||
ev_uint8_t evcb_closure;
|
||||
/* allows us to adopt for different types of events */
|
||||
union {
|
||||
void (*evcb_callback)(evutil_socket_t, short, void *);
|
||||
void (*evcb_selfcb)(struct event_callback *, void *);
|
||||
void (*evcb_evfinalize)(struct event *, void *);
|
||||
void (*evcb_cbfinalize)(struct event_callback *, void *);
|
||||
} evcb_cb_union;
|
||||
void *evcb_arg;
|
||||
};
|
||||
|
||||
struct event_base;
|
||||
struct event {
|
||||
struct event_callback ev_evcallback;
|
||||
|
||||
/* for managing timeouts */
|
||||
union {
|
||||
TAILQ_ENTRY(event) ev_next_with_common_timeout;
|
||||
int min_heap_idx;
|
||||
} ev_timeout_pos;
|
||||
evutil_socket_t ev_fd;
|
||||
|
||||
struct event_base *ev_base;
|
||||
|
||||
union {
|
||||
/* used for io events */
|
||||
struct {
|
||||
LIST_ENTRY (event) ev_io_next;
|
||||
struct timeval ev_timeout;
|
||||
} ev_io;
|
||||
|
||||
/* used by signal events */
|
||||
struct {
|
||||
LIST_ENTRY (event) ev_signal_next;
|
||||
short ev_ncalls;
|
||||
/* Allows deletes in callback */
|
||||
short *ev_pncalls;
|
||||
} ev_signal;
|
||||
} ev_;
|
||||
|
||||
short ev_events;
|
||||
short ev_res; /* result passed to event callback */
|
||||
struct timeval ev_timeout;
|
||||
};
|
||||
|
||||
TAILQ_HEAD (event_list, event);
|
||||
|
||||
#ifdef EVENT_DEFINED_TQENTRY_
|
||||
#undef TAILQ_ENTRY
|
||||
#endif
|
||||
|
||||
#ifdef EVENT_DEFINED_TQHEAD_
|
||||
#undef TAILQ_HEAD
|
||||
#endif
|
||||
|
||||
LIST_HEAD (event_dlist, event);
|
||||
|
||||
#ifdef EVENT_DEFINED_LISTENTRY_
|
||||
#undef LIST_ENTRY
|
||||
#endif
|
||||
|
||||
#ifdef EVENT_DEFINED_LISTHEAD_
|
||||
#undef LIST_HEAD
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EVENT2_EVENT_STRUCT_H_INCLUDED_ */
|
||||
1192
thirdparty/include/libevent/event2/http.h
vendored
Normal file
1192
thirdparty/include/libevent/event2/http.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
94
thirdparty/include/libevent/event2/http_compat.h
vendored
Normal file
94
thirdparty/include/libevent/event2/http_compat.h
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
#ifndef EVENT2_HTTP_COMPAT_H_INCLUDED_
|
||||
#define EVENT2_HTTP_COMPAT_H_INCLUDED_
|
||||
|
||||
/** @file event2/http_compat.h
|
||||
|
||||
Potentially non-threadsafe versions of the functions in http.h: provided
|
||||
only for backwards compatibility.
|
||||
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <event2/event-config.h>
|
||||
#ifdef EVENT__HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef EVENT__HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
/* For int types. */
|
||||
#include <event2/util.h>
|
||||
|
||||
/**
|
||||
* Start an HTTP server on the specified address and port
|
||||
*
|
||||
* @deprecated It does not allow an event base to be specified
|
||||
*
|
||||
* @param address the address to which the HTTP server should be bound
|
||||
* @param port the port number on which the HTTP server should listen
|
||||
* @return a pointer to a newly initialized evhttp server structure
|
||||
* or NULL on error
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
struct evhttp *evhttp_start(const char *address, ev_uint16_t port);
|
||||
|
||||
/**
|
||||
* A connection object that can be used to for making HTTP requests. The
|
||||
* connection object tries to establish the connection when it is given an
|
||||
* http request object.
|
||||
*
|
||||
* @deprecated It does not allow an event base to be specified
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
struct evhttp_connection *evhttp_connection_new(
|
||||
const char *address, ev_uint16_t port);
|
||||
|
||||
/**
|
||||
* Associates an event base with the connection - can only be called
|
||||
* on a freshly created connection object that has not been used yet.
|
||||
*
|
||||
* @deprecated XXXX Why?
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evhttp_connection_set_base(struct evhttp_connection *evcon,
|
||||
struct event_base *base);
|
||||
|
||||
|
||||
/** Returns the request URI */
|
||||
#define evhttp_request_uri evhttp_request_get_uri
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EVENT2_EVENT_COMPAT_H_INCLUDED_ */
|
||||
152
thirdparty/include/libevent/event2/http_struct.h
vendored
Normal file
152
thirdparty/include/libevent/event2/http_struct.h
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
#ifndef EVENT2_HTTP_STRUCT_H_INCLUDED_
|
||||
#define EVENT2_HTTP_STRUCT_H_INCLUDED_
|
||||
|
||||
/** @file event2/http_struct.h
|
||||
|
||||
Data structures for http. Using these structures may hurt forward
|
||||
compatibility with later versions of Libevent: be careful!
|
||||
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <event2/event-config.h>
|
||||
#ifdef EVENT__HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef EVENT__HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
/* For int types. */
|
||||
#include <event2/util.h>
|
||||
|
||||
/**
|
||||
* the request structure that a server receives.
|
||||
* WARNING: expect this structure to change. I will try to provide
|
||||
* reasonable accessors.
|
||||
*/
|
||||
struct evhttp_request {
|
||||
#if defined(TAILQ_ENTRY)
|
||||
TAILQ_ENTRY(evhttp_request) next;
|
||||
#else
|
||||
struct {
|
||||
struct evhttp_request *tqe_next;
|
||||
struct evhttp_request **tqe_prev;
|
||||
} next;
|
||||
#endif
|
||||
|
||||
/* the connection object that this request belongs to */
|
||||
struct evhttp_connection *evcon;
|
||||
int flags;
|
||||
/** The request obj owns the evhttp connection and needs to free it */
|
||||
#define EVHTTP_REQ_OWN_CONNECTION 0x0001
|
||||
/** Request was made via a proxy */
|
||||
#define EVHTTP_PROXY_REQUEST 0x0002
|
||||
/** The request object is owned by the user; the user must free it */
|
||||
#define EVHTTP_USER_OWNED 0x0004
|
||||
/** The request will be used again upstack; freeing must be deferred */
|
||||
#define EVHTTP_REQ_DEFER_FREE 0x0008
|
||||
/** The request should be freed upstack */
|
||||
#define EVHTTP_REQ_NEEDS_FREE 0x0010
|
||||
|
||||
struct evkeyvalq *input_headers;
|
||||
struct evkeyvalq *output_headers;
|
||||
|
||||
/* address of the remote host and the port connection came from */
|
||||
char *remote_host;
|
||||
ev_uint16_t remote_port;
|
||||
|
||||
/* cache of the hostname for evhttp_request_get_host */
|
||||
char *host_cache;
|
||||
|
||||
enum evhttp_request_kind kind;
|
||||
enum evhttp_cmd_type type;
|
||||
|
||||
size_t headers_size;
|
||||
size_t body_size;
|
||||
|
||||
char *uri; /* uri after HTTP request was parsed */
|
||||
struct evhttp_uri *uri_elems; /* uri elements */
|
||||
|
||||
char major; /* HTTP Major number */
|
||||
char minor; /* HTTP Minor number */
|
||||
|
||||
int response_code; /* HTTP Response code */
|
||||
char *response_code_line; /* Readable response */
|
||||
|
||||
struct evbuffer *input_buffer; /* read data */
|
||||
ev_int64_t ntoread;
|
||||
unsigned chunked:1, /* a chunked request */
|
||||
userdone:1; /* the user has sent all data */
|
||||
|
||||
struct evbuffer *output_buffer; /* outgoing post or data */
|
||||
|
||||
/* Callback */
|
||||
void (*cb)(struct evhttp_request *, void *);
|
||||
void *cb_arg;
|
||||
|
||||
/*
|
||||
* Chunked data callback - call for each completed chunk if
|
||||
* specified. If not specified, all the data is delivered via
|
||||
* the regular callback.
|
||||
*/
|
||||
void (*chunk_cb)(struct evhttp_request *, void *);
|
||||
|
||||
/*
|
||||
* Callback added for forked-daapd so they can collect ICY
|
||||
* (shoutcast) metadata from the http header. If return
|
||||
* int is negative the connection will be closed.
|
||||
*/
|
||||
int (*header_cb)(struct evhttp_request *, void *);
|
||||
|
||||
/*
|
||||
* Error callback - called when error is occured.
|
||||
* @see evhttp_request_error for error types.
|
||||
*
|
||||
* @see evhttp_request_set_error_cb()
|
||||
*/
|
||||
void (*error_cb)(enum evhttp_request_error, void *);
|
||||
|
||||
/*
|
||||
* Send complete callback - called when the request is actually
|
||||
* sent and completed.
|
||||
*/
|
||||
void (*on_complete_cb)(struct evhttp_request *, void *);
|
||||
void *on_complete_cb_arg;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EVENT2_HTTP_STRUCT_H_INCLUDED_ */
|
||||
|
||||
80
thirdparty/include/libevent/event2/keyvalq_struct.h
vendored
Normal file
80
thirdparty/include/libevent/event2/keyvalq_struct.h
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
#ifndef EVENT2_KEYVALQ_STRUCT_H_INCLUDED_
|
||||
#define EVENT2_KEYVALQ_STRUCT_H_INCLUDED_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Fix so that people don't have to run with <sys/queue.h> */
|
||||
/* XXXX This code is duplicated with event_struct.h */
|
||||
#ifndef TAILQ_ENTRY
|
||||
#define EVENT_DEFINED_TQENTRY_
|
||||
#define TAILQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *tqe_next; /* next element */ \
|
||||
struct type **tqe_prev; /* address of previous next element */ \
|
||||
}
|
||||
#endif /* !TAILQ_ENTRY */
|
||||
|
||||
#ifndef TAILQ_HEAD
|
||||
#define EVENT_DEFINED_TQHEAD_
|
||||
#define TAILQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *tqh_first; \
|
||||
struct type **tqh_last; \
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Key-Value pairs. Can be used for HTTP headers but also for
|
||||
* query argument parsing.
|
||||
*/
|
||||
struct evkeyval {
|
||||
TAILQ_ENTRY(evkeyval) next;
|
||||
|
||||
char *key;
|
||||
char *value;
|
||||
};
|
||||
|
||||
TAILQ_HEAD (evkeyvalq, evkeyval);
|
||||
|
||||
/* XXXX This code is duplicated with event_struct.h */
|
||||
#ifdef EVENT_DEFINED_TQENTRY_
|
||||
#undef TAILQ_ENTRY
|
||||
#endif
|
||||
|
||||
#ifdef EVENT_DEFINED_TQHEAD_
|
||||
#undef TAILQ_HEAD
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
192
thirdparty/include/libevent/event2/listener.h
vendored
Normal file
192
thirdparty/include/libevent/event2/listener.h
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
#ifndef EVENT2_LISTENER_H_INCLUDED_
|
||||
#define EVENT2_LISTENER_H_INCLUDED_
|
||||
|
||||
#include <event2/visibility.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <event2/event.h>
|
||||
|
||||
struct sockaddr;
|
||||
struct evconnlistener;
|
||||
|
||||
/**
|
||||
A callback that we invoke when a listener has a new connection.
|
||||
|
||||
@param listener The evconnlistener
|
||||
@param fd The new file descriptor
|
||||
@param addr The source address of the connection
|
||||
@param socklen The length of addr
|
||||
@param user_arg the pointer passed to evconnlistener_new()
|
||||
*/
|
||||
typedef void (*evconnlistener_cb)(struct evconnlistener *, evutil_socket_t, struct sockaddr *, int socklen, void *);
|
||||
|
||||
/**
|
||||
A callback that we invoke when a listener encounters a non-retriable error.
|
||||
|
||||
@param listener The evconnlistener
|
||||
@param user_arg the pointer passed to evconnlistener_new()
|
||||
*/
|
||||
typedef void (*evconnlistener_errorcb)(struct evconnlistener *, void *);
|
||||
|
||||
/** Flag: Indicates that we should not make incoming sockets nonblocking
|
||||
* before passing them to the callback. */
|
||||
#define LEV_OPT_LEAVE_SOCKETS_BLOCKING (1u<<0)
|
||||
/** Flag: Indicates that freeing the listener should close the underlying
|
||||
* socket. */
|
||||
#define LEV_OPT_CLOSE_ON_FREE (1u<<1)
|
||||
/** Flag: Indicates that we should set the close-on-exec flag, if possible */
|
||||
#define LEV_OPT_CLOSE_ON_EXEC (1u<<2)
|
||||
/** Flag: Indicates that we should disable the timeout (if any) between when
|
||||
* this socket is closed and when we can listen again on the same port. */
|
||||
#define LEV_OPT_REUSEABLE (1u<<3)
|
||||
/** Flag: Indicates that the listener should be locked so it's safe to use
|
||||
* from multiple threadcs at once. */
|
||||
#define LEV_OPT_THREADSAFE (1u<<4)
|
||||
/** Flag: Indicates that the listener should be created in disabled
|
||||
* state. Use evconnlistener_enable() to enable it later. */
|
||||
#define LEV_OPT_DISABLED (1u<<5)
|
||||
/** Flag: Indicates that the listener should defer accept() until data is
|
||||
* available, if possible. Ignored on platforms that do not support this.
|
||||
*
|
||||
* This option can help performance for protocols where the client transmits
|
||||
* immediately after connecting. Do not use this option if your protocol
|
||||
* _doesn't_ start out with the client transmitting data, since in that case
|
||||
* this option will sometimes cause the kernel to never tell you about the
|
||||
* connection.
|
||||
*
|
||||
* This option is only supported by evconnlistener_new_bind(): it can't
|
||||
* work with evconnlistener_new_fd(), since the listener needs to be told
|
||||
* to use the option before it is actually bound.
|
||||
*/
|
||||
#define LEV_OPT_DEFERRED_ACCEPT (1u<<6)
|
||||
/** Flag: Indicates that we ask to allow multiple servers (processes or
|
||||
* threads) to bind to the same port if they each set the option.
|
||||
*
|
||||
* SO_REUSEPORT is what most people would expect SO_REUSEADDR to be, however
|
||||
* SO_REUSEPORT does not imply SO_REUSEADDR.
|
||||
*
|
||||
* This is only available on Linux and kernel 3.9+
|
||||
*/
|
||||
#define LEV_OPT_REUSEABLE_PORT (1u<<7)
|
||||
/** Flag: Indicates that the listener wants to work only in IPv6 socket.
|
||||
*
|
||||
* According to RFC3493 and most Linux distributions, default value is to
|
||||
* work in IPv4-mapped mode. If there is a requirement to bind same port
|
||||
* on same ip addresses but different handlers for both IPv4 and IPv6,
|
||||
* it is required to set IPV6_V6ONLY socket option to be sure that the
|
||||
* code works as expected without affected by bindv6only sysctl setting in
|
||||
* system.
|
||||
*
|
||||
* This socket option also supported by Windows.
|
||||
*/
|
||||
#define LEV_OPT_BIND_IPV6ONLY (1u<<8)
|
||||
|
||||
/**
|
||||
Allocate a new evconnlistener object to listen for incoming TCP connections
|
||||
on a given file descriptor.
|
||||
|
||||
@param base The event base to associate the listener with.
|
||||
@param cb A callback to be invoked when a new connection arrives. If the
|
||||
callback is NULL, the listener will be treated as disabled until the
|
||||
callback is set.
|
||||
@param ptr A user-supplied pointer to give to the callback.
|
||||
@param flags Any number of LEV_OPT_* flags
|
||||
@param backlog Passed to the listen() call to determine the length of the
|
||||
acceptable connection backlog. Set to -1 for a reasonable default.
|
||||
Set to 0 if the socket is already listening.
|
||||
@param fd The file descriptor to listen on. It must be a nonblocking
|
||||
file descriptor, and it should already be bound to an appropriate
|
||||
port and address.
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
struct evconnlistener *evconnlistener_new(struct event_base *base,
|
||||
evconnlistener_cb cb, void *ptr, unsigned flags, int backlog,
|
||||
evutil_socket_t fd);
|
||||
/**
|
||||
Allocate a new evconnlistener object to listen for incoming TCP connections
|
||||
on a given address.
|
||||
|
||||
@param base The event base to associate the listener with.
|
||||
@param cb A callback to be invoked when a new connection arrives. If the
|
||||
callback is NULL, the listener will be treated as disabled until the
|
||||
callback is set.
|
||||
@param ptr A user-supplied pointer to give to the callback.
|
||||
@param flags Any number of LEV_OPT_* flags
|
||||
@param backlog Passed to the listen() call to determine the length of the
|
||||
acceptable connection backlog. Set to -1 for a reasonable default.
|
||||
@param addr The address to listen for connections on.
|
||||
@param socklen The length of the address.
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
struct evconnlistener *evconnlistener_new_bind(struct event_base *base,
|
||||
evconnlistener_cb cb, void *ptr, unsigned flags, int backlog,
|
||||
const struct sockaddr *sa, int socklen);
|
||||
/**
|
||||
Disable and deallocate an evconnlistener.
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evconnlistener_free(struct evconnlistener *lev);
|
||||
/**
|
||||
Re-enable an evconnlistener that has been disabled.
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evconnlistener_enable(struct evconnlistener *lev);
|
||||
/**
|
||||
Stop listening for connections on an evconnlistener.
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evconnlistener_disable(struct evconnlistener *lev);
|
||||
|
||||
/** Return an evconnlistener's associated event_base. */
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
struct event_base *evconnlistener_get_base(struct evconnlistener *lev);
|
||||
|
||||
/** Return the socket that an evconnlistner is listening on. */
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
evutil_socket_t evconnlistener_get_fd(struct evconnlistener *lev);
|
||||
|
||||
/** Change the callback on the listener to cb and its user_data to arg.
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evconnlistener_set_cb(struct evconnlistener *lev,
|
||||
evconnlistener_cb cb, void *arg);
|
||||
|
||||
/** Set an evconnlistener's error callback. */
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evconnlistener_set_error_cb(struct evconnlistener *lev,
|
||||
evconnlistener_errorcb errorcb);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
626
thirdparty/include/libevent/event2/rpc.h
vendored
Normal file
626
thirdparty/include/libevent/event2/rpc.h
vendored
Normal file
@@ -0,0 +1,626 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
#ifndef EVENT2_RPC_H_INCLUDED_
|
||||
#define EVENT2_RPC_H_INCLUDED_
|
||||
|
||||
/* For int types. */
|
||||
#include <event2/util.h>
|
||||
#include <event2/visibility.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @file rpc.h
|
||||
*
|
||||
* This header files provides basic support for an RPC server and client.
|
||||
*
|
||||
* To support RPCs in a server, every supported RPC command needs to be
|
||||
* defined and registered.
|
||||
*
|
||||
* EVRPC_HEADER(SendCommand, Request, Reply);
|
||||
*
|
||||
* SendCommand is the name of the RPC command.
|
||||
* Request is the name of a structure generated by event_rpcgen.py.
|
||||
* It contains all parameters relating to the SendCommand RPC. The
|
||||
* server needs to fill in the Reply structure.
|
||||
* Reply is the name of a structure generated by event_rpcgen.py. It
|
||||
* contains the answer to the RPC.
|
||||
*
|
||||
* To register an RPC with an HTTP server, you need to first create an RPC
|
||||
* base with:
|
||||
*
|
||||
* struct evrpc_base *base = evrpc_init(http);
|
||||
*
|
||||
* A specific RPC can then be registered with
|
||||
*
|
||||
* EVRPC_REGISTER(base, SendCommand, Request, Reply, FunctionCB, arg);
|
||||
*
|
||||
* when the server receives an appropriately formatted RPC, the user callback
|
||||
* is invoked. The callback needs to fill in the reply structure.
|
||||
*
|
||||
* void FunctionCB(EVRPC_STRUCT(SendCommand)* rpc, void *arg);
|
||||
*
|
||||
* To send the reply, call EVRPC_REQUEST_DONE(rpc);
|
||||
*
|
||||
* See the regression test for an example.
|
||||
*/
|
||||
|
||||
/**
|
||||
Determines if the member has been set in the message
|
||||
|
||||
@param msg the message to inspect
|
||||
@param member the member variable to test for presences
|
||||
@return 1 if it's present or 0 otherwise.
|
||||
*/
|
||||
#define EVTAG_HAS(msg, member) \
|
||||
((msg)->member##_set == 1)
|
||||
|
||||
#ifndef EVENT2_RPC_COMPAT_H_INCLUDED_
|
||||
|
||||
/**
|
||||
Assigns a value to the member in the message.
|
||||
|
||||
@param msg the message to which to assign a value
|
||||
@param member the name of the member variable
|
||||
@param value the value to assign
|
||||
*/
|
||||
#define EVTAG_ASSIGN(msg, member, value) \
|
||||
(*(msg)->base->member##_assign)((msg), (value))
|
||||
/**
|
||||
Assigns a value to the member in the message.
|
||||
|
||||
@param msg the message to which to assign a value
|
||||
@param member the name of the member variable
|
||||
@param value the value to assign
|
||||
@param len the length of the value
|
||||
*/
|
||||
#define EVTAG_ASSIGN_WITH_LEN(msg, member, value, len) \
|
||||
(*(msg)->base->member##_assign)((msg), (value), (len))
|
||||
/**
|
||||
Returns the value for a member.
|
||||
|
||||
@param msg the message from which to get the value
|
||||
@param member the name of the member variable
|
||||
@param pvalue a pointer to the variable to hold the value
|
||||
@return 0 on success, -1 otherwise.
|
||||
*/
|
||||
#define EVTAG_GET(msg, member, pvalue) \
|
||||
(*(msg)->base->member##_get)((msg), (pvalue))
|
||||
/**
|
||||
Returns the value for a member.
|
||||
|
||||
@param msg the message from which to get the value
|
||||
@param member the name of the member variable
|
||||
@param pvalue a pointer to the variable to hold the value
|
||||
@param plen a pointer to the length of the value
|
||||
@return 0 on success, -1 otherwise.
|
||||
*/
|
||||
#define EVTAG_GET_WITH_LEN(msg, member, pvalue, plen) \
|
||||
(*(msg)->base->member##_get)((msg), (pvalue), (plen))
|
||||
|
||||
#endif /* EVENT2_RPC_COMPAT_H_INCLUDED_ */
|
||||
|
||||
/**
|
||||
Adds a value to an array.
|
||||
*/
|
||||
#define EVTAG_ARRAY_ADD_VALUE(msg, member, value) \
|
||||
(*(msg)->base->member##_add)((msg), (value))
|
||||
/**
|
||||
Allocates a new entry in the array and returns it.
|
||||
*/
|
||||
#define EVTAG_ARRAY_ADD(msg, member) \
|
||||
(*(msg)->base->member##_add)(msg)
|
||||
/**
|
||||
Gets a variable at the specified offset from the array.
|
||||
*/
|
||||
#define EVTAG_ARRAY_GET(msg, member, offset, pvalue) \
|
||||
(*(msg)->base->member##_get)((msg), (offset), (pvalue))
|
||||
/**
|
||||
Returns the number of entries in the array.
|
||||
*/
|
||||
#define EVTAG_ARRAY_LEN(msg, member) ((msg)->member##_length)
|
||||
|
||||
|
||||
struct evbuffer;
|
||||
struct event_base;
|
||||
struct evrpc_req_generic;
|
||||
struct evrpc_request_wrapper;
|
||||
struct evrpc;
|
||||
|
||||
/** The type of a specific RPC Message
|
||||
*
|
||||
* @param rpcname the name of the RPC message
|
||||
*/
|
||||
#define EVRPC_STRUCT(rpcname) struct evrpc_req__##rpcname
|
||||
|
||||
struct evhttp_request;
|
||||
struct evrpc_status;
|
||||
struct evrpc_hook_meta;
|
||||
|
||||
/** Creates the definitions and prototypes for an RPC
|
||||
*
|
||||
* You need to use EVRPC_HEADER to create structures and function prototypes
|
||||
* needed by the server and client implementation. The structures have to be
|
||||
* defined in an .rpc file and converted to source code via event_rpcgen.py
|
||||
*
|
||||
* @param rpcname the name of the RPC
|
||||
* @param reqstruct the name of the RPC request structure
|
||||
* @param replystruct the name of the RPC reply structure
|
||||
* @see EVRPC_GENERATE()
|
||||
*/
|
||||
#define EVRPC_HEADER(rpcname, reqstruct, rplystruct) \
|
||||
EVRPC_STRUCT(rpcname) { \
|
||||
struct evrpc_hook_meta *hook_meta; \
|
||||
struct reqstruct* request; \
|
||||
struct rplystruct* reply; \
|
||||
struct evrpc* rpc; \
|
||||
struct evhttp_request* http_req; \
|
||||
struct evbuffer* rpc_data; \
|
||||
}; \
|
||||
EVENT2_EXPORT_SYMBOL \
|
||||
int evrpc_send_request_##rpcname(struct evrpc_pool *, \
|
||||
struct reqstruct *, struct rplystruct *, \
|
||||
void (*)(struct evrpc_status *, \
|
||||
struct reqstruct *, struct rplystruct *, void *cbarg), \
|
||||
void *);
|
||||
|
||||
struct evrpc_pool;
|
||||
|
||||
/** use EVRPC_GENERATE instead */
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
struct evrpc_request_wrapper *evrpc_make_request_ctx(
|
||||
struct evrpc_pool *pool, void *request, void *reply,
|
||||
const char *rpcname,
|
||||
void (*req_marshal)(struct evbuffer*, void *),
|
||||
void (*rpl_clear)(void *),
|
||||
int (*rpl_unmarshal)(void *, struct evbuffer *),
|
||||
void (*cb)(struct evrpc_status *, void *, void *, void *),
|
||||
void *cbarg);
|
||||
|
||||
/** Creates a context structure that contains rpc specific information.
|
||||
*
|
||||
* EVRPC_MAKE_CTX is used to populate a RPC specific context that
|
||||
* contains information about marshaling the RPC data types.
|
||||
*
|
||||
* @param rpcname the name of the RPC
|
||||
* @param reqstruct the name of the RPC request structure
|
||||
* @param replystruct the name of the RPC reply structure
|
||||
* @param pool the evrpc_pool over which to make the request
|
||||
* @param request a pointer to the RPC request structure object
|
||||
* @param reply a pointer to the RPC reply structure object
|
||||
* @param cb the callback function to call when the RPC has completed
|
||||
* @param cbarg the argument to supply to the callback
|
||||
*/
|
||||
#define EVRPC_MAKE_CTX(rpcname, reqstruct, rplystruct, \
|
||||
pool, request, reply, cb, cbarg) \
|
||||
evrpc_make_request_ctx(pool, request, reply, \
|
||||
#rpcname, \
|
||||
(void (*)(struct evbuffer *, void *))reqstruct##_marshal, \
|
||||
(void (*)(void *))rplystruct##_clear, \
|
||||
(int (*)(void *, struct evbuffer *))rplystruct##_unmarshal, \
|
||||
(void (*)(struct evrpc_status *, void *, void *, void *))cb, \
|
||||
cbarg)
|
||||
|
||||
/** Generates the code for receiving and sending an RPC message
|
||||
*
|
||||
* EVRPC_GENERATE is used to create the code corresponding to sending
|
||||
* and receiving a particular RPC message
|
||||
*
|
||||
* @param rpcname the name of the RPC
|
||||
* @param reqstruct the name of the RPC request structure
|
||||
* @param replystruct the name of the RPC reply structure
|
||||
* @see EVRPC_HEADER()
|
||||
*/
|
||||
#define EVRPC_GENERATE(rpcname, reqstruct, rplystruct) \
|
||||
int evrpc_send_request_##rpcname(struct evrpc_pool *pool, \
|
||||
struct reqstruct *request, struct rplystruct *reply, \
|
||||
void (*cb)(struct evrpc_status *, \
|
||||
struct reqstruct *, struct rplystruct *, void *cbarg), \
|
||||
void *cbarg) { \
|
||||
return evrpc_send_request_generic(pool, request, reply, \
|
||||
(void (*)(struct evrpc_status *, void *, void *, void *))cb, \
|
||||
cbarg, \
|
||||
#rpcname, \
|
||||
(void (*)(struct evbuffer *, void *))reqstruct##_marshal, \
|
||||
(void (*)(void *))rplystruct##_clear, \
|
||||
(int (*)(void *, struct evbuffer *))rplystruct##_unmarshal); \
|
||||
}
|
||||
|
||||
/** Provides access to the HTTP request object underlying an RPC
|
||||
*
|
||||
* Access to the underlying http object; can be used to look at headers or
|
||||
* for getting the remote ip address
|
||||
*
|
||||
* @param rpc_req the rpc request structure provided to the server callback
|
||||
* @return an struct evhttp_request object that can be inspected for
|
||||
* HTTP headers or sender information.
|
||||
*/
|
||||
#define EVRPC_REQUEST_HTTP(rpc_req) (rpc_req)->http_req
|
||||
|
||||
/** completes the server response to an rpc request */
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evrpc_request_done(struct evrpc_req_generic *req);
|
||||
|
||||
/** accessors for request and reply */
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void *evrpc_get_request(struct evrpc_req_generic *req);
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void *evrpc_get_reply(struct evrpc_req_generic *req);
|
||||
|
||||
/** Creates the reply to an RPC request
|
||||
*
|
||||
* EVRPC_REQUEST_DONE is used to answer a request; the reply is expected
|
||||
* to have been filled in. The request and reply pointers become invalid
|
||||
* after this call has finished.
|
||||
*
|
||||
* @param rpc_req the rpc request structure provided to the server callback
|
||||
*/
|
||||
#define EVRPC_REQUEST_DONE(rpc_req) do { \
|
||||
struct evrpc_req_generic *req_ = (struct evrpc_req_generic *)(rpc_req); \
|
||||
evrpc_request_done(req_); \
|
||||
} while (0)
|
||||
|
||||
|
||||
struct evrpc_base;
|
||||
struct evhttp;
|
||||
|
||||
/* functions to start up the rpc system */
|
||||
|
||||
/** Creates a new rpc base from which RPC requests can be received
|
||||
*
|
||||
* @param server a pointer to an existing HTTP server
|
||||
* @return a newly allocated evrpc_base struct or NULL if an error occurred
|
||||
* @see evrpc_free()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
struct evrpc_base *evrpc_init(struct evhttp *server);
|
||||
|
||||
/**
|
||||
* Frees the evrpc base
|
||||
*
|
||||
* For now, you are responsible for making sure that no rpcs are ongoing.
|
||||
*
|
||||
* @param base the evrpc_base object to be freed
|
||||
* @see evrpc_init
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evrpc_free(struct evrpc_base *base);
|
||||
|
||||
/** register RPCs with the HTTP Server
|
||||
*
|
||||
* registers a new RPC with the HTTP server, each RPC needs to have
|
||||
* a unique name under which it can be identified.
|
||||
*
|
||||
* @param base the evrpc_base structure in which the RPC should be
|
||||
* registered.
|
||||
* @param name the name of the RPC
|
||||
* @param request the name of the RPC request structure
|
||||
* @param reply the name of the RPC reply structure
|
||||
* @param callback the callback that should be invoked when the RPC
|
||||
* is received. The callback has the following prototype
|
||||
* void (*callback)(EVRPC_STRUCT(Message)* rpc, void *arg)
|
||||
* @param cbarg an additional parameter that can be passed to the callback.
|
||||
* The parameter can be used to carry around state.
|
||||
*/
|
||||
#define EVRPC_REGISTER(base, name, request, reply, callback, cbarg) \
|
||||
evrpc_register_generic(base, #name, \
|
||||
(void (*)(struct evrpc_req_generic *, void *))callback, cbarg, \
|
||||
(void *(*)(void *))request##_new_with_arg, NULL, \
|
||||
(void (*)(void *))request##_free, \
|
||||
(int (*)(void *, struct evbuffer *))request##_unmarshal, \
|
||||
(void *(*)(void *))reply##_new_with_arg, NULL, \
|
||||
(void (*)(void *))reply##_free, \
|
||||
(int (*)(void *))reply##_complete, \
|
||||
(void (*)(struct evbuffer *, void *))reply##_marshal)
|
||||
|
||||
/**
|
||||
Low level function for registering an RPC with a server.
|
||||
|
||||
Use EVRPC_REGISTER() instead.
|
||||
|
||||
@see EVRPC_REGISTER()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evrpc_register_rpc(struct evrpc_base *, struct evrpc *,
|
||||
void (*)(struct evrpc_req_generic*, void *), void *);
|
||||
|
||||
/**
|
||||
* Unregisters an already registered RPC
|
||||
*
|
||||
* @param base the evrpc_base object from which to unregister an RPC
|
||||
* @param name the name of the rpc to unregister
|
||||
* @return -1 on error or 0 when successful.
|
||||
* @see EVRPC_REGISTER()
|
||||
*/
|
||||
#define EVRPC_UNREGISTER(base, name) evrpc_unregister_rpc((base), #name)
|
||||
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evrpc_unregister_rpc(struct evrpc_base *base, const char *name);
|
||||
|
||||
/*
|
||||
* Client-side RPC support
|
||||
*/
|
||||
|
||||
struct evhttp_connection;
|
||||
struct evrpc_status;
|
||||
|
||||
/** launches an RPC and sends it to the server
|
||||
*
|
||||
* EVRPC_MAKE_REQUEST() is used by the client to send an RPC to the server.
|
||||
*
|
||||
* @param name the name of the RPC
|
||||
* @param pool the evrpc_pool that contains the connection objects over which
|
||||
* the request should be sent.
|
||||
* @param request a pointer to the RPC request structure - it contains the
|
||||
* data to be sent to the server.
|
||||
* @param reply a pointer to the RPC reply structure. It is going to be filled
|
||||
* if the request was answered successfully
|
||||
* @param cb the callback to invoke when the RPC request has been answered
|
||||
* @param cbarg an additional argument to be passed to the client
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
#define EVRPC_MAKE_REQUEST(name, pool, request, reply, cb, cbarg) \
|
||||
evrpc_send_request_##name((pool), (request), (reply), (cb), (cbarg))
|
||||
|
||||
/**
|
||||
Makes an RPC request based on the provided context.
|
||||
|
||||
This is a low-level function and should not be used directly
|
||||
unless a custom context object is provided. Use EVRPC_MAKE_REQUEST()
|
||||
instead.
|
||||
|
||||
@param ctx a context from EVRPC_MAKE_CTX()
|
||||
@returns 0 on success, -1 otherwise.
|
||||
@see EVRPC_MAKE_REQUEST(), EVRPC_MAKE_CTX()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evrpc_make_request(struct evrpc_request_wrapper *ctx);
|
||||
|
||||
/** creates an rpc connection pool
|
||||
*
|
||||
* a pool has a number of connections associated with it.
|
||||
* rpc requests are always made via a pool.
|
||||
*
|
||||
* @param base a pointer to an struct event_based object; can be left NULL
|
||||
* in singled-threaded applications
|
||||
* @return a newly allocated struct evrpc_pool object or NULL if an error
|
||||
* occurred
|
||||
* @see evrpc_pool_free()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
struct evrpc_pool *evrpc_pool_new(struct event_base *base);
|
||||
/** frees an rpc connection pool
|
||||
*
|
||||
* @param pool a pointer to an evrpc_pool allocated via evrpc_pool_new()
|
||||
* @see evrpc_pool_new()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evrpc_pool_free(struct evrpc_pool *pool);
|
||||
|
||||
/**
|
||||
* Adds a connection over which rpc can be dispatched to the pool.
|
||||
*
|
||||
* The connection object must have been newly created.
|
||||
*
|
||||
* @param pool the pool to which to add the connection
|
||||
* @param evcon the connection to add to the pool.
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evrpc_pool_add_connection(struct evrpc_pool *pool,
|
||||
struct evhttp_connection *evcon);
|
||||
|
||||
/**
|
||||
* Removes a connection from the pool.
|
||||
*
|
||||
* The connection object must have been newly created.
|
||||
*
|
||||
* @param pool the pool from which to remove the connection
|
||||
* @param evcon the connection to remove from the pool.
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evrpc_pool_remove_connection(struct evrpc_pool *pool,
|
||||
struct evhttp_connection *evcon);
|
||||
|
||||
/**
|
||||
* Sets the timeout in secs after which a request has to complete. The
|
||||
* RPC is completely aborted if it does not complete by then. Setting
|
||||
* the timeout to 0 means that it never timeouts and can be used to
|
||||
* implement callback type RPCs.
|
||||
*
|
||||
* Any connection already in the pool will be updated with the new
|
||||
* timeout. Connections added to the pool after set_timeout has be
|
||||
* called receive the pool timeout only if no timeout has been set
|
||||
* for the connection itself.
|
||||
*
|
||||
* @param pool a pointer to a struct evrpc_pool object
|
||||
* @param timeout_in_secs the number of seconds after which a request should
|
||||
* timeout and a failure be returned to the callback.
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evrpc_pool_set_timeout(struct evrpc_pool *pool, int timeout_in_secs);
|
||||
|
||||
/**
|
||||
* Hooks for changing the input and output of RPCs; this can be used to
|
||||
* implement compression, authentication, encryption, ...
|
||||
*/
|
||||
|
||||
enum EVRPC_HOOK_TYPE {
|
||||
EVRPC_INPUT, /**< apply the function to an input hook */
|
||||
EVRPC_OUTPUT /**< apply the function to an output hook */
|
||||
};
|
||||
|
||||
#ifndef _WIN32
|
||||
/** Deprecated alias for EVRPC_INPUT. Not available on windows, where it
|
||||
* conflicts with platform headers. */
|
||||
#define INPUT EVRPC_INPUT
|
||||
/** Deprecated alias for EVRPC_OUTPUT. Not available on windows, where it
|
||||
* conflicts with platform headers. */
|
||||
#define OUTPUT EVRPC_OUTPUT
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Return value from hook processing functions
|
||||
*/
|
||||
|
||||
enum EVRPC_HOOK_RESULT {
|
||||
EVRPC_TERMINATE = -1, /**< indicates the rpc should be terminated */
|
||||
EVRPC_CONTINUE = 0, /**< continue processing the rpc */
|
||||
EVRPC_PAUSE = 1 /**< pause processing request until resumed */
|
||||
};
|
||||
|
||||
/** adds a processing hook to either an rpc base or rpc pool
|
||||
*
|
||||
* If a hook returns TERMINATE, the processing is aborted. On CONTINUE,
|
||||
* the request is immediately processed after the hook returns. If the
|
||||
* hook returns PAUSE, request processing stops until evrpc_resume_request()
|
||||
* has been called.
|
||||
*
|
||||
* The add functions return handles that can be used for removing hooks.
|
||||
*
|
||||
* @param vbase a pointer to either struct evrpc_base or struct evrpc_pool
|
||||
* @param hook_type either INPUT or OUTPUT
|
||||
* @param cb the callback to call when the hook is activated
|
||||
* @param cb_arg an additional argument for the callback
|
||||
* @return a handle to the hook so it can be removed later
|
||||
* @see evrpc_remove_hook()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void *evrpc_add_hook(void *vbase,
|
||||
enum EVRPC_HOOK_TYPE hook_type,
|
||||
int (*cb)(void *, struct evhttp_request *, struct evbuffer *, void *),
|
||||
void *cb_arg);
|
||||
|
||||
/** removes a previously added hook
|
||||
*
|
||||
* @param vbase a pointer to either struct evrpc_base or struct evrpc_pool
|
||||
* @param hook_type either INPUT or OUTPUT
|
||||
* @param handle a handle returned by evrpc_add_hook()
|
||||
* @return 1 on success or 0 on failure
|
||||
* @see evrpc_add_hook()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evrpc_remove_hook(void *vbase,
|
||||
enum EVRPC_HOOK_TYPE hook_type,
|
||||
void *handle);
|
||||
|
||||
/** resume a paused request
|
||||
*
|
||||
* @param vbase a pointer to either struct evrpc_base or struct evrpc_pool
|
||||
* @param ctx the context pointer provided to the original hook call
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evrpc_resume_request(void *vbase, void *ctx, enum EVRPC_HOOK_RESULT res);
|
||||
|
||||
/** adds meta data to request
|
||||
*
|
||||
* evrpc_hook_add_meta() allows hooks to add meta data to a request. for
|
||||
* a client request, the meta data can be inserted by an outgoing request hook
|
||||
* and retrieved by the incoming request hook.
|
||||
*
|
||||
* @param ctx the context provided to the hook call
|
||||
* @param key a NUL-terminated c-string
|
||||
* @param data the data to be associated with the key
|
||||
* @param data_size the size of the data
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evrpc_hook_add_meta(void *ctx, const char *key,
|
||||
const void *data, size_t data_size);
|
||||
|
||||
/** retrieves meta data previously associated
|
||||
*
|
||||
* evrpc_hook_find_meta() can be used to retrieve meta data associated to a
|
||||
* request by a previous hook.
|
||||
* @param ctx the context provided to the hook call
|
||||
* @param key a NUL-terminated c-string
|
||||
* @param data pointer to a data pointer that will contain the retrieved data
|
||||
* @param data_size pointer to the size of the data
|
||||
* @return 0 on success or -1 on failure
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evrpc_hook_find_meta(void *ctx, const char *key,
|
||||
void **data, size_t *data_size);
|
||||
|
||||
/**
|
||||
* returns the connection object associated with the request
|
||||
*
|
||||
* @param ctx the context provided to the hook call
|
||||
* @return a pointer to the evhttp_connection object or NULL if an error
|
||||
* occurred
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
struct evhttp_connection *evrpc_hook_get_connection(void *ctx);
|
||||
|
||||
/**
|
||||
Function for sending a generic RPC request.
|
||||
|
||||
Do not call this function directly, use EVRPC_MAKE_REQUEST() instead.
|
||||
|
||||
@see EVRPC_MAKE_REQUEST()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evrpc_send_request_generic(struct evrpc_pool *pool,
|
||||
void *request, void *reply,
|
||||
void (*cb)(struct evrpc_status *, void *, void *, void *),
|
||||
void *cb_arg,
|
||||
const char *rpcname,
|
||||
void (*req_marshal)(struct evbuffer *, void *),
|
||||
void (*rpl_clear)(void *),
|
||||
int (*rpl_unmarshal)(void *, struct evbuffer *));
|
||||
|
||||
/**
|
||||
Function for registering a generic RPC with the RPC base.
|
||||
|
||||
Do not call this function directly, use EVRPC_REGISTER() instead.
|
||||
|
||||
@see EVRPC_REGISTER()
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evrpc_register_generic(struct evrpc_base *base, const char *name,
|
||||
void (*callback)(struct evrpc_req_generic *, void *), void *cbarg,
|
||||
void *(*req_new)(void *), void *req_new_arg, void (*req_free)(void *),
|
||||
int (*req_unmarshal)(void *, struct evbuffer *),
|
||||
void *(*rpl_new)(void *), void *rpl_new_arg, void (*rpl_free)(void *),
|
||||
int (*rpl_complete)(void *),
|
||||
void (*rpl_marshal)(struct evbuffer *, void *));
|
||||
|
||||
/** accessors for obscure and undocumented functionality */
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
struct evrpc_pool* evrpc_request_get_pool(struct evrpc_request_wrapper *ctx);
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evrpc_request_set_pool(struct evrpc_request_wrapper *ctx,
|
||||
struct evrpc_pool *pool);
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evrpc_request_set_cb(struct evrpc_request_wrapper *ctx,
|
||||
void (*cb)(struct evrpc_status*, void *request, void *reply, void *arg),
|
||||
void *cb_arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EVENT2_RPC_H_INCLUDED_ */
|
||||
61
thirdparty/include/libevent/event2/rpc_compat.h
vendored
Normal file
61
thirdparty/include/libevent/event2/rpc_compat.h
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
#ifndef EVENT2_RPC_COMPAT_H_INCLUDED_
|
||||
#define EVENT2_RPC_COMPAT_H_INCLUDED_
|
||||
|
||||
/** @file event2/rpc_compat.h
|
||||
|
||||
Deprecated versions of the functions in rpc.h: provided only for
|
||||
backwards compatibility.
|
||||
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** backwards compatible accessors that work only with gcc */
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
|
||||
#undef EVTAG_ASSIGN
|
||||
#undef EVTAG_GET
|
||||
#undef EVTAG_ADD
|
||||
|
||||
#define EVTAG_ASSIGN(msg, member, args...) \
|
||||
(*(msg)->base->member##_assign)(msg, ## args)
|
||||
#define EVTAG_GET(msg, member, args...) \
|
||||
(*(msg)->base->member##_get)(msg, ## args)
|
||||
#define EVTAG_ADD(msg, member, args...) \
|
||||
(*(msg)->base->member##_add)(msg, ## args)
|
||||
#endif
|
||||
#define EVTAG_LEN(msg, member) ((msg)->member##_length)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EVENT2_EVENT_COMPAT_H_INCLUDED_ */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user