88 Commits

Author SHA1 Message Date
staylightblow8
86866e7c60 fix: fix compile warning of telnetd
Signed-off-by: staylightblow8 <liudf0716@gmail.com>
2023-09-22 21:27:38 +08:00
staylightblow8
2e20d95333 modify adding user and setting password method
Signed-off-by: staylightblow8 <liudf0716@gmail.com>
2023-09-22 20:49:44 +08:00
staylightblow8
30ef8fe688 Update azure-pipelines.yml 2023-09-09 18:22:56 +08:00
staylightblow8
f6faea35bd Update azure-pipelines.yml 2023-09-09 18:14:17 +08:00
staylightblow8
d137205777 Update version.h 2023-09-09 18:00:36 +08:00
staylightblow8
3a029dbe25 Update azure-pipelines.yml 2023-09-09 17:48:59 +08:00
staylightblow8
4b1242a837 Set up CI with Azure Pipelines
[skip ci]
2023-09-09 17:38:18 +08:00
staylightblow8
4615827afd Delete colab_xfrpc.ipynb 2023-09-02 22:17:08 +08:00
staylightblow8
f8b8418610 colab support
add xfrpc.ipynb
2023-09-02 21:56:10 +08:00
staylightblow8
b5f4a2aa13 使用 Colaboratory 创建 2023-09-02 19:56:44 +08:00
staylightblow8
0caec598b2 plugins: add telnetd plugin
Signed-off-by: staylightblow8 <liudf0716@gmail.com>
2023-09-02 19:35:39 +08:00
staylightblow8
6296108fcb feat: add udp support
Signed-off-by: staylightblow8 <liudf0716@gmail.com>
2023-08-27 20:47:39 +08:00
staylightblow8
bd13b67bb6 feat: add tcp redir service for mstsc service
cause mstsc cant change its dest port, so xfrpc do it

Signed-off-by: staylightblow8 <liudf0716@gmail.com>
2023-08-05 21:36:20 +08:00
staylightblow8
711bb918e7 Update README.md 2023-06-22 16:38:03 +08:00
staylightblow8
8d25270d32 Update README.md 2023-06-22 16:37:20 +08:00
staylightblow8
4b6178d9b6 set version 2.6.633 2023-05-28 11:01:26 +08:00
staylightblow8
ee8089b646 Create rules 2023-04-24 09:24:02 +08:00
staylightblow8
04614da70a feature: add load balance feature
Signed-off-by: staylightblow8 <liudf0716@gmail.com>
2023-04-22 11:14:40 +08:00
staylightblow8
dd90cbd5ae Merge branch 'dev' 2023-04-09 21:01:56 +08:00
liuxc0116
4f8ea81333 fix bug: add locations error
Signed-off-by: liuxc0116 <liuxc0116@foxmail.com>
2023-04-09 20:32:15 +08:00
staylightblow8
0516791805 Merge remote-tracking branch 'origin' 2023-04-09 20:11:20 +08:00
liuxc0116
dc2f8298e7 fix bug: add locations error
Signed-off-by: liuxc0116 <liuxc0116@foxmail.com>
2023-04-06 09:34:33 +08:00
staylightblow8
9cdc7b77e3 feature: add socks5
Signed-off-by: staylightblow8 <liudf0716@gmail.com>
2023-04-02 21:31:35 +08:00
helintongh
c3fe0158f8 feature:add asan library for detect memory leak
Signed-off-by: helintongh <agh6399@gmail.com>
2023-04-02 19:53:13 +08:00
staylightblow8
6a30714038 Update azure-pipelines-xfrpc.yml 2023-04-02 12:42:01 +08:00
staylightblow8
5ccea20716 Update azure-pipelines.yml for Azure Pipelines 2023-04-02 12:40:54 +08:00
staylightblow8
a8498897e7 Update azure-pipelines.yml for Azure Pipelines 2023-04-02 11:57:19 +08:00
staylightblow8
0a14878bef Update azure-pipelines.yml for Azure Pipelines 2023-03-30 09:41:49 +08:00
staylightblow8
c55e2e2e60 Set up CI with Azure Pipelines
[skip ci]
2023-03-29 20:31:23 +08:00
staylightblow8
4b211160f3 Create azure-pipelines-xfrpc.yml 2023-03-28 09:44:50 +08:00
staylightblow8
112e664980 Set up CI with Azure Pipelines
[skip ci]
2023-03-26 21:03:46 +08:00
staylightblow8
1373126939 circleci: add circleci to the project
Signed-off-by: staylightblow8 <liudf0716@gmail.com>
2023-03-26 20:32:27 +08:00
staylightblow8
6cb60c8b30 Update control.c 2023-02-12 08:46:56 +08:00
helintongh
a644c73cd5 fix: Set the CROSS C COMPILER variable through the cmake variable to adapt to more compilers
Signed-off-by: helintongh <agh6399@qq.com>
2023-02-05 20:59:01 +08:00
helintongh
0fa3f17aa2 feat: add cross compile
Signed-off-by: helintongh <agh6399@qq.com>
2023-02-05 20:59:01 +08:00
staylightblow8
5e00022c88 Update linux.yml 2023-02-04 14:27:26 +08:00
staylightblow8
96d0abc8b0 Update linux.yml 2023-02-04 14:24:32 +08:00
staylightblow8
7cced34933 Update linux.yml 2023-02-04 14:13:58 +08:00
staylightblow8
cb5062de3f Update linux.yml 2023-02-04 14:00:07 +08:00
staylightblow8
e657805327 Update README.md 2023-02-04 10:31:01 +08:00
JimLee1996
5be58a4414 ifname for padavan
Signed-off-by: JimLee1996 <59061463@qq.com>
2023-01-31 10:55:07 +08:00
JimLee1996
c91b1c7f30 fix #31:
process_flags may call `del_proxy_client_by_stream_id()`
which will cause segmentation fault if *stream is cleaned

Signed-off-by: JimLee1996 <59061463@qq.com>
2023-01-31 10:55:07 +08:00
staylightblow8
35ca79be82 bump version to 2.1.606 2023-01-21 14:16:46 +08:00
staylightblow8
405ae15530 doc: change logo image 2023-01-18 10:02:50 +08:00
staylightblow8
08a909322c doc: revise README content
Signed-off-by: Dengfeng Liu <liudf0716@gmail.com>
2023-01-17 10:07:32 +00:00
helintongh
e20a54cd11 [doc]annotation-static library build need cmake version > 3.1
Signed-off-by: helintongh <agh6399@gmail.com>
2023-01-13 16:45:44 +08:00
helintongh
3e31841509 [feat]add 3rdparty source for cross platform
Signed-off-by: helintongh <agh6399@gmail.com>
2023-01-13 16:45:44 +08:00
helintongh
28ceccd55c feature:support build xfrpc by build-in static library
build xfrpc by build-in static library.
Possible solution for [#17](https://github.com/liudf0716/xfrpc/issues/17) and [#20](https://github.com/liudf0716/xfrpc/issues/20)

Signed-off-by: helintongh <agh6399@gmail.com>
2023-01-09 18:05:22 +08:00
Tianyu Li
36647b91ef build: support build static binary
Build static binary in Alpine container.

Signed-off-by: Tianyu Li <tianyulee@gmail.com>
2023-01-09 10:29:07 +08:00
Dengfeng Liu
39b5d81231 fix: fix the following bug
https://github.com/liudf0716/xfrpc/issues/19

Signed-off-by: Dengfeng Liu <liudf0716@gmail.com>
2023-01-05 05:50:38 +00:00
Dengfeng Liu
b6cf043a52 fix: fix bug of github issue https://github.com/liudf0716/xfrpc/issues/18
Signed-off-by: Dengfeng Liu <liudf0716@gmail.com>
2023-01-03 09:50:41 +00:00
Your Name
5d8f776826 fix: fix which bug
Signed-off-by: Haibin Zhu <2499243103@qq.com>
2022-12-21 11:19:38 +08:00
Your Name
0d0399f770 Signed-off-by: Haibin Zhu <2499243103@qq.com>
On branch A-lullaby/xfrpc
 Changes to be committed:
	modified:   tcpmux.c
 fix: fix which bug
2022-12-19 17:33:19 +08:00
staylightblow8
34346837c8 update 2022-12-04 15:14:47 +08:00
Dengfeng Liu
03daef0f29 fix: memory leak and assert trigger bug
Signed-off-by: Dengfeng Liu <liudf0716@gmail.com>
2022-12-04 07:11:50 +00:00
staylightblow8
d98c4d2c94 Update README.md 2022-11-30 17:48:13 +08:00
Dengfeng Liu
1143cfda1b fix: when proxy service ip is wrong, while cause xfrpc exit
Signed-off-by: Dengfeng Liu <liudf0716@gmail.com>
2022-11-24 09:19:34 +00:00
Dengfeng Liu
17838cfc45 fix: xfrpc exit when wrong proxy configured
if configure wrong proxy, custom visiting proxy service will cause xfrpc exit

Signed-off-by: Dengfeng Liu <liudf0716@gmail.com>
2022-11-20 11:59:01 +00:00
staylightblow8
b018bb84e4 Update README.md 2022-11-19 09:12:34 +08:00
staylightblow8
a1bd4373ff Update README.md 2022-11-19 09:11:37 +08:00
staylightblow8
63c84386ca Update README.md 2022-11-18 17:31:51 +08:00
staylightblow8
d9ff2e1a62 release version 1.11.587 2022-11-16 10:22:03 +08:00
Dengfeng Liu
3396100bc4 clean: clean unused function
Signed-off-by: Dengfeng Liu <liudf0716@gmail.com>
2022-11-14 08:42:17 +00:00
DengfengLiu
c53693be69 refactor: refactor tcp mux
Signed-off-by: DengfengLiu <liu_df@qq.com>
2022-11-13 11:09:36 +00:00
staylightblow8
855f602e2f support openssl > 3.0 2022-10-20 10:45:37 +08:00
staylightblow8
fd9a5ae249 Update README.md 2022-10-18 11:37:02 +08:00
Dengfeng Liu
61d5243678 clean code of config
Signed-off-by: Dengfeng Liu <liudf0716@gmail.com>
2022-07-25 14:37:16 +08:00
staylightblow8
e75a4dda25 update version 2022-07-24 21:20:01 +08:00
staylightblow8
65bfe5c03c Update README.md 2022-07-12 10:06:53 +08:00
Dengfeng Liu
b7c3e1f80b fix: check whether tcp mux header or not mor strictly
Signed-off-by: Dengfeng Liu <liudf0716@gmail.com>
2022-07-11 16:10:08 +08:00
staylightblow8
3fb01ce735 Update version.h 2022-06-30 14:01:39 +08:00
staylightblow8
f14562b26b Delete xfrpc.conf 2022-06-30 14:00:25 +08:00
staylightblow8
d4f35909c5 Delete xfrpc.init 2022-06-30 14:00:18 +08:00
staylightblow8
1ee2b1ff56 Delete Makefile 2022-06-30 13:59:55 +08:00
staylightblow8
cab6e8a20f Update README.md 2022-06-28 17:58:25 +08:00
staylightblow8
e53f8e1c94 Update README.md 2022-06-15 09:50:10 +08:00
staylightblow8
23819fcb44 Update README.md 2022-06-14 09:51:19 +08:00
staylightblow8
51930c855f Update CONTRIBUTING.md 2022-06-13 11:30:55 +08:00
Dengfeng Liu
690a6f4feb fix: interval ping process
Signed-off-by: Dengfeng Liu <liudf0716@gmail.com>
2022-06-08 11:09:34 +08:00
Dengfeng Liu
56e4020969 feat: heartbeat_timeout process
Signed-off-by: Dengfeng Liu <liudf0716@gmail.com>
2022-06-07 15:18:37 +08:00
Dengfeng Liu
e06a9a40a3 fix: parse proxy response error when remote_address is domain
Signed-off-by: Dengfeng Liu <liudf0716@gmail.com>
2022-06-07 14:20:27 +08:00
Dengfeng Liu
767d2859f9 feat: when xfrpc disconnected from frps, it should reconnect repeatly
Signed-off-by: Dengfeng Liu <liudf0716@gmail.com>
2022-06-07 10:08:38 +08:00
Dengfeng Liu
fa0a273865 Merge branch 'master' of https://github.com/liudf0716/xfrpc 2022-06-06 15:27:56 +08:00
Dengfeng Liu
030a7b8784 fix: when reconnect frps should send proxy conf again
Signed-off-by: Dengfeng Liu <liudf0716@gmail.com>
2022-06-06 15:26:36 +08:00
staylightblow8
d2cd54d831 Update README.md 2022-06-06 15:13:25 +08:00
Dengfeng Liu
9c90f6b5cd Merge branch 'master' of https://github.com/liudf0716/xfrpc 2022-06-05 17:39:27 +08:00
Dengfeng Liu
d1e2f549a7 fix: fix the following bug
when xfrpc connected frps, then stop frps and start frps
the bug happen

Signed-off-by: Dengfeng Liu <liudf0716@gmail.com>
2022-06-05 17:26:20 +08:00
staylightblow8
ffa9e1ad97 Update README.md 2022-06-01 16:36:56 +08:00
2093 changed files with 844504 additions and 874 deletions

75
.circleci/config.yml Normal file
View 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

View File

@@ -12,20 +12,14 @@ on:
jobs:
build:
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: install other depend lib
run: |
sudo apt-get update -y
sudo apt-get install -y libjson-c-dev
sudo apt-get install -y libevent-dev
- name: compile xfrpc
run: |
mkdir build
cd build
cmake ..
cmake -D THIRDPARTY_STATIC_BUILD=ON ..
make

1
.gitignore vendored
View File

@@ -44,3 +44,4 @@ xfrpc
xfrp_test_server
bin
.vscode
build

View File

@@ -1,21 +1,62 @@
cmake_minimum_required(VERSION 2.6)
cmake_minimum_required(VERSION 2.8.12)
project(xfrp C)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
find_package(LibEvent)
if(NOT LibEvent_FOUND)
message(FATAL_ERROR "libevent2 not found!")
endif(NOT LibEvent_FOUND)
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(OpenSSL)
if(NOT OPENSSL_FOUND)
message(FATAL_ERROR "OpenSSL not found!")
endif(NOT OPENSSL_FOUND)
find_package(LibEvent)
if(NOT LibEvent_FOUND)
message(FATAL_ERROR "LibEvent not found!")
endif(NOT LibEvent_FOUND)
find_package(JSON-C REQUIRED)
include_directories(${JSON-C_INCLUDE_DIR})
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
@@ -34,27 +75,38 @@ set(src_xfrpc
common.c
login.c
proxy_tcp.c
proxy_udp.c
proxy_ftp.c
proxy.c
tcpmux.c
tcp_redir.c
)
set(src_xfrpc_plugins
plugins/telnetd.c)
set(libs
ssl
crypto
event
z
m
json-c)
json-c
crypt
pthread)
set(test_libs
event
)
ADD_DEFINITIONS(-Wall -g --std=gnu99)
ADD_DEFINITIONS(-Wall -g -Wno-deprecated-declarations --std=gnu99 ${asan_c_flags})
add_executable(xfrpc ${src_xfrpc})
target_link_libraries(xfrpc ${libs})
if (STATIC_BUILD STREQUAL "ON")
add_link_options(-static)
endif (STATIC_BUILD)
add_executable(xfrpc ${src_xfrpc} ${src_xfrpc_plugins})
target_link_libraries(xfrpc ${libs} ${static_libs} ${asan_c_libs})
install(TARGETS xfrpc
RUNTIME DESTINATION bin

View File

@@ -27,7 +27,7 @@ If you want to contribute to [xfrpc](https://github.com/liudf0716/xfrpc), 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!

187
README.md
View File

@@ -1,10 +1,10 @@
![xfrpc](https://github.com/liudf0716/xfrpc/blob/master/logo.png)
![xfrpc](https://user-images.githubusercontent.com/1182593/213063003-73501d3b-1a22-4f4a-8f3f-4ca3268b5bee.png)
## What is xfrpc
`xfrpc` is [frp](https://github.com/fatedier/frp) client implemented by c language for [OpenWRT](https://github.com/openwrt/openwrt)
The motivation to start xfrpc project is that we are OpenWRTer, and openwrt usually run in devices which have limit ROM and RAM space, however frpc always need more space and memory; therefore we launched xfrpc project.
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.
## Development Status
@@ -18,18 +18,24 @@ the following table is detail compatible feature:
| 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 |
| vistor | No | Yes |
| stcp | No | Yes |
## Architecture
![Architecture](https://github.com/fatedier/frp/blob/dev/doc/pic/architecture.png?raw=true)
Architecture quote from [frp](https://github.com/fatedier/frp) project, replace frpc with xfrpc.
![Architecture](https://user-images.githubusercontent.com/1182593/196329678-1781b4e9-2355-4863-be3f-e128b31cc82c.png)
## Sequence Diagram
@@ -76,34 +82,126 @@ sequenceDiagram
```
## Compile
## How to build
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
### Build on Ubuntu 20.04.3 LTS
Before compile xfrp, please install `libevent` and `json-c` in your system.
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:
Install json-c libevent in ubuntu 20.04 LTS
```shell
sudo apt-get install -y libjson-c-dev
sudo apt-get install -y libevent-dev
```
sudo apt-get update
sudo apt-get install -y libjson-c-dev libevent-dev libssl-dev
```
```shell
git clone https://github.com/liudf0716/xfrpc.git
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.
## Quick start
### 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/${YOUR_GITHUB_ACCOUNT_NAME}/xfrpc.git
cd xfrp
mkdir build
cmake -D THIRDPARTY_STATIC_BUILD=ON ..
make
```
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.
It's important to note that you will need cmake version greater than 3.1 to use this feature.
### 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
```
CMAKE_C_COMPILER flag is the path of your cross compiler.I recommend that you put this in an environment variable.
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
Under project root directory
```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
frps use latest release 0.42.0
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
@@ -111,13 +209,9 @@ frps use latest release 0.42.0
bind_port = 7000
```
run frps
+ xfrpc tcp support
```
./frps -c frps.ini
```
+ xfrpc tcp
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
@@ -132,7 +226,21 @@ local_port = 22
remote_port = 6128
```
+ xfrpc http
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
@@ -140,14 +248,27 @@ remote_port = 6128
server_addr = x.x.x.x
server_port = 7000
[web]
[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
```
@@ -158,6 +279,16 @@ xfrpc -c frpc_mini.ini -f -d 7
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/liudf0716/xfrpc/blob/master/CONTRIBUTING.md) for details on submitting patches and the contribution workflow.
@@ -184,8 +315,12 @@ QQ群 [331230369](https://jq.qq.com/?_wv=1027&k=47QGEhL)
![微信打赏](https://user-images.githubusercontent.com/1182593/169465249-db1b495e-078e-4cab-91fc-96dab3320b06.png)
<!--
## 广告
想学习OpenWrt开发但是摸不着门道自学没毅力基础太差怕太难学不会跟着佐大学OpenWrt开发入门培训班助你能学有所成
报名地址https://forgotfun.org/2018/04/openwrt-training-2018.html
-->

46
azure-pipelines.yml Normal file
View 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'

View 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'

115
client.c
View File

@@ -41,7 +41,6 @@
#include "uthash.h"
#include "control.h"
#include "config.h"
#include "const.h"
#include "uthash.h"
#include "zip.h"
#include "common.h"
@@ -60,26 +59,44 @@ xfrp_worker_event_cb(struct bufferevent *bev, short what, void *ctx)
}
}
static void
void
xfrp_proxy_event_cb(struct bufferevent *bev, short what, void *ctx)
{
struct proxy_client *client = ctx;
assert(client);
if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
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));
tcp_mux_send_win_update_fin(client->ctl_bev, client->stream_id);
client->stream_state = LOCAL_CLOSE;
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, "client [%d] connected", client->stream_id);
//client->stream_state = ESTABLISHED;
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;
}
}
}
}
int
@@ -94,6 +111,30 @@ is_ftp_proxy(const struct proxy_service *ps)
return 0;
}
int
is_socks5_proxy(const struct proxy_service *ps)
{
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_xfrp_tunnel(struct proxy_client *client)
@@ -122,23 +163,41 @@ start_xfrp_tunnel(struct proxy_client *client)
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);
del_proxy_client(client);
// 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,
ps->remote_port,
ps->local_ip ? ps->local_ip:"::1",
ps->local_ip ? ps->local_ip:"127.0.0.1",
ps->local_port);
#define PREDICT_FALSE(x) 0
bufferevent_data_cb proxy_s2c_recv, proxy_c2s_recv;
if (is_ftp_proxy(client->ps)) {
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
@@ -153,6 +212,8 @@ start_xfrp_tunnel(struct proxy_client *client)
bufferevent_enable(client->ctl_bev, EV_READ|EV_WRITE);
}
bufferevent_setcb(client->local_proxy_bev,
proxy_c2s_recv,
NULL,
@@ -178,11 +239,12 @@ send_client_data_tail(struct proxy_client *client)
static void
free_proxy_client(struct proxy_client *client)
{
debug(LOG_DEBUG, "free client %d", client->stream_id);
if (client->local_proxy_bev) bufferevent_free(client->local_proxy_bev);
free(client);
}
void
static void
del_proxy_client(struct proxy_client *client)
{
if (!client || !all_pc ) {
@@ -195,6 +257,15 @@ del_proxy_client(struct proxy_client *client)
free_proxy_client(client);
}
void
del_proxy_client_by_stream_id(uint32_t sid)
{
del_stream(sid);
struct proxy_client *pc = get_proxy_client(sid);
del_proxy_client(pc);
}
struct proxy_client *
get_proxy_client(uint32_t sid)
{
@@ -209,8 +280,7 @@ new_proxy_client()
struct proxy_client *client = calloc(1, sizeof(struct proxy_client));
assert(client);
client->stream_id = get_next_session_id();
client->send_window = 128*1024;
client->stream_state = INIT;
init_tmux_stream(&client->stream, client->stream_id, INIT);
HASH_ADD_INT(all_pc, stream_id, client);
return client;
@@ -219,11 +289,14 @@ new_proxy_client()
void
clear_all_proxy_client()
{
if (!all_pc) return;
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;
}

View File

@@ -39,21 +39,39 @@ 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; // xfrpc proxy <---> frps
struct bufferevent *local_proxy_bev; // xfrpc proxy <---> local service
struct base_conf *bconf;
struct tmux_stream stream;
uint32_t stream_id;
uint32_t send_window;
enum tcp_mux_state stream_state;
int connected;
int work_started;
struct proxy_service *ps;
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;
};
@@ -65,6 +83,7 @@ struct proxy_service {
int use_encryption;
int use_compression;
// tcp or udp
char *local_ip;
int remote_port;
int remote_data_port;
@@ -78,6 +97,15 @@ struct proxy_service {
char *http_user;
char *http_pwd;
// load balance
char *group;
char *group_key;
// plugin
char *plugin;
char *plugin_user;
char *plugin_pwd;
// private arguments
UT_hash_handle hh;
};
@@ -89,7 +117,7 @@ struct proxy_service {
// if client has data-tail(not NULL), client value will be changed
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);
struct proxy_client *get_proxy_client(uint32_t sid);
@@ -97,8 +125,14 @@ 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_

View File

@@ -282,11 +282,11 @@ function(from_hex HEX DEC)
set(${DEC} ${_res} PARENT_SCOPE)
endfunction()
if (OPENSSL_INCLUDE_DIR)
if(OPENSSL_INCLUDE_DIR AND EXISTS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h")
file(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h" openssl_version_str
REGEX "^# *define[\t ]+OPENSSL_VERSION_NUMBER[\t ]+0x([0-9a-fA-F])+.*")
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
@@ -315,6 +315,25 @@ if (OPENSSL_INCLUDE_DIR)
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 ()

118
colab/xfrpc.ipynb Normal file
View 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": []
}
]
}

315
config.c
View File

@@ -28,9 +28,11 @@
#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"
@@ -41,49 +43,40 @@
#include "utils.h"
#include "version.h"
// define a list of type in array
static const char *valid_types[] = {
"tcp",
"udp",
"mstsc",
"socks5",
"http",
"https",
NULL
};
static struct common_conf *c_conf;
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);
SAFE_FREE(c_conf->server_ip);
};
void set_common_server_ip(const char *ip)
{
struct common_conf *c_conf = get_common_config();
c_conf->server_ip = strdup(ip);
assert(c_conf->server_ip);
debug(LOG_DEBUG, "server IP address: [%s]", c_conf->server_ip);
}
void free_base_config(struct base_conf *bconf)
{
if (bconf->name) free(bconf->name);
if (bconf->auth_token) free(bconf->auth_token);
if (bconf->privilege_token) free(bconf->privilege_token);
if (bconf->host_header_rewrite) free(bconf->host_header_rewrite);
if (bconf->subdomain) free(bconf->subdomain);
}
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;
@@ -91,43 +84,42 @@ 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")) {
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) {
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);
@@ -135,15 +127,29 @@ static void dump_proxy_service(const int index, struct proxy_service *ps)
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;
@@ -153,7 +159,8 @@ static void dump_all_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;
@@ -168,9 +175,9 @@ static struct proxy_service *new_proxy_service(const char *name)
ps->proxy_type = NULL;
ps->use_encryption = 0;
ps->local_port = -1;
ps->remote_port = -1;
ps->remote_data_port = -1;
ps->local_port = 0;
ps->remote_port = 0;
ps->remote_data_port = 0;
ps->use_compression = 0;
ps->use_encryption = 0;
@@ -181,11 +188,19 @@ 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;
return ps;
}
// create a new proxy service with suffix "_ftp_data_proxy"
static void new_ftp_data_proxy_service(struct proxy_service *ftp_ps)
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);
@@ -213,6 +228,106 @@ static void new_ftp_data_proxy_service(struct proxy_service *ftp_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, "mstsc") == 0) {
if (ps->remote_port == 0 || ps->local_port == 0) {
debug(LOG_ERR, "Proxy [%s] error: remote_port or local_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 = 23;
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);
}
}
}
static int
proxy_service_handler(void *user, const char *sect, const char *nm, const char *value)
{
@@ -262,72 +377,68 @@ proxy_service_handler(void *user, const char *sect, const char *nm, const char *
ps->remote_data_port = atoi(value);
} else if (MATCH_NAME("http_user")) {
ps->http_user = strdup(value);
assert(ps->http_user);
} else if (MATCH_NAME("http_pwd")) {
ps->http_pwd = strdup(value);
assert(ps->http_pwd);
} else if (MATCH_NAME("subdomain")) {
ps->subdomain = strdup(value);
assert(ps->http_pwd);
} else if (MATCH_NAME("custom_domains")) {
ps->custom_domains = strdup(value);
assert(ps->custom_domains);
} else if (MATCH_NAME("locations")) {
ps->locations = strdup(value);
assert(ps->locations);
} else if (MATCH_NAME("host_header_rewrite")) {
ps->host_header_rewrite = strdup(value);
assert(ps->host_header_rewrite);
} 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 {
debug(LOG_ERR, "unknown option %s in section %s", nm, section);
SAFE_FREE(section);
return 0;
}
// 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, "mstsc") == 0) {
// if ps->proxy_type is mstsc, and ps->local_port is not set, set it to 3389
// start a thread to listen on local_port, and forward data to remote_port
if (ps->local_port == 0)
ps->local_port = DEFAULT_MSTSC_PORT;
} 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;
#define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0
if (MATCH("common", "server_addr")) {
SAFE_FREE(config->server_addr);
int addr_len = strlen(value) + 1;
config->server_addr = (char *)calloc(1, addr_len);
config->server_addr = strdup(value);
assert(config->server_addr);
if(dns_unified(value, config->server_addr, addr_len)) {
debug(LOG_ERR, "error: server_addr [%s] is invalid!", value);
exit(0);
}
if (is_valid_ip_address(value))
set_common_server_ip(value);
} 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);
assert(config->http_proxy);
} else if (MATCH("common", "log_file")) {
SAFE_FREE(config->log_file);
config->log_file = strdup(value);
assert(config->log_file);
} else if (MATCH("common", "log_way")) {
SAFE_FREE(config->log_way);
config->log_way = strdup(value);
assert(config->log_way);
} else if (MATCH("common", "log_level")) {
SAFE_FREE(config->log_level);
config->log_level = strdup(value);
assert(config->log_level);
} 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);
assert(config->privilege_token);
} else if (MATCH("common", "heartbeat_interval")) {
config->heartbeat_interval = atoi(value);
} else if (MATCH("common", "heartbeat_timeout")) {
@@ -336,10 +447,6 @@ static int common_handler(void *user, const char *section, const char *name, con
SAFE_FREE(config->auth_token);
config->auth_token = strdup(value);
assert(config->auth_token);
} else if (MATCH("common", "user")) {
SAFE_FREE(config->user);
config->user = strdup(value);
assert(config->user);
} else if (MATCH("common", "tcp_mux")) {
config->tcp_mux = atoi(value);
config->tcp_mux = !!config->tcp_mux;
@@ -347,7 +454,8 @@ static int common_handler(void *user, const char *section, const char *name, con
return 1;
}
static void init_common_conf(struct common_conf *config)
static void
init_common_conf(struct common_conf *config)
{
if (!config)
return;
@@ -355,18 +463,9 @@ static void init_common_conf(struct common_conf *config)
config->server_addr = strdup("0.0.0.0");
assert(config->server_addr);
config->server_port = 7000;
config->log_file = strdup("console");
assert(config->log_file);
config->log_way = strdup("console");
assert(config->log_way);
config->log_level = strdup("info");
assert(config->log_level);
config->log_max_days = 3;
config->heartbeat_interval = 30;
config->heartbeat_timeout = 60;
config->heartbeat_timeout = 90;
config->tcp_mux = 1;
config->user = NULL;
config->server_ip = NULL;
config->is_router = 0;
}

View File

@@ -29,36 +29,18 @@
#include "client.h"
#include "common.h"
#define DEFAULT_MSTSC_PORT 3389
#define DEFAULT_SOCKS5_PORT 1980
#define FTP_RMT_CTL_PROXY_SUFFIX "_ftp_remote_ctl_proxy"
struct base_conf{
char *name;
char *auth_token;
int use_encryption;
int use_gzip;
int privilege_mode;
char *privilege_token;
int pool_count;
char *host_header_rewrite;
char *subdomain;
};
// common config
//client common config
struct common_conf {
char *server_addr; /* default 0.0.0.0 */
char *server_ip;
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 *auth_token;
int heartbeat_interval; /* default 10 */
int heartbeat_timeout; /* default 30 */
int tcp_mux; /* default 0 */
char *user;
/* private fields */
int is_router; // to sign router (Openwrt/LEDE) or not
@@ -68,18 +50,16 @@ struct common_conf *get_common_config();
void free_common_config();
void free_base_config(struct base_conf *bconf);
void load_config(const char *confile);
char *get_ftp_data_proxy_name(const char *ftp_proxy_name);
void set_common_server_ip(const char *ip);
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_

38
const.h
View File

@@ -1,38 +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 xfrpc constant parameter define
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
*/
#ifndef _CONST_H_
#define _CONST_H_
// server status
enum server_status {
Idle = 0,
Working,
Closed
};
#endif

380
control.c
View File

@@ -35,12 +35,12 @@
#include <json-c/json.h>
#include <syslog.h>
#include <unistd.h>
#include <time.h>
#include "debug.h"
#include "client.h"
#include "uthash.h"
#include "config.h"
#include "const.h"
#include "msg.h"
#include "control.h"
#include "uthash.h"
@@ -49,37 +49,41 @@
#include "common.h"
#include "login.h"
#include "tcpmux.h"
#include "proxy.h"
static struct control *main_ctl;
static int clients_conn_signel = 0;
static int client_connected = 0;
static int is_login = 0;
static time_t pong_time = 0;
static void sync_new_work_connection(struct bufferevent *bev, uint32_t sid);
static void new_work_connection(struct bufferevent *bev, struct tmux_stream *stream);
static void recv_cb(struct bufferevent *bev, void *ctx);
static void clear_main_control();
static void start_base_connect();
static void keep_control_alive();
static int
is_client_connected()
{
return clients_conn_signel;
return client_connected;
}
static int
client_connected(int is_connected)
set_client_status(int is_connected)
{
if (is_connected)
clients_conn_signel = 1;
client_connected = 1;
else
clients_conn_signel = 0;
client_connected = 0;
return clients_conn_signel;
return client_connected;
}
static int
set_client_work_start(struct proxy_client *client, int is_start_work)
{
assert(client->ps);
if (is_start_work) {
assert(client->ps);
client->work_started = 1;
}else
client->work_started = 0;
@@ -102,12 +106,12 @@ client_start_event_cb(struct bufferevent *bev, short what, void *ctx)
}
debug(LOG_ERR, "Proxy connect server [%s:%d] error: %s", c_conf->server_addr, c_conf->server_port, strerror(errno));
bufferevent_free(bev);
del_proxy_client(client);
del_proxy_client_by_stream_id(client->stream_id);
} else if (what & BEV_EVENT_CONNECTED) {
bufferevent_setcb(bev, recv_cb, NULL, client_start_event_cb, client);
bufferevent_enable(bev, EV_READ|EV_WRITE);
sync_new_work_connection(bev, 0);
client_connected(1);
new_work_connection(bev, &main_ctl->stream);
set_client_status(1);
debug(LOG_INFO, "proxy service start");
}
}
@@ -123,7 +127,8 @@ new_client_connect()
if (c_conf->tcp_mux) {
debug(LOG_DEBUG, "new client through tcp mux: %d", client->stream_id);
client->ctl_bev = main_ctl->connect_bev;
sync_new_work_connection(client->ctl_bev, client->stream_id);
send_window_update(client->ctl_bev, &client->stream, 0);
new_work_connection(client->ctl_bev, &client->stream);
return;
}
@@ -158,6 +163,10 @@ start_proxy_services()
debug(LOG_ERR, "proxy service is invalid!");
return;
}
if (strcmp(ps->proxy_type, "mstsc") == 0) {
debug(LOG_ERR, "no need to send mstsc service!");
continue;
}
send_new_proxy(ps);
}
}
@@ -173,14 +182,13 @@ ping()
}
char *ping_msg = "{}";
send_enc_msg_frp_server(bout, TypePing, ping_msg, strlen(ping_msg), main_ctl->stream_id);
send_enc_msg_frp_server(bout, TypePing, ping_msg, strlen(ping_msg), &main_ctl->stream);
}
static void
sync_new_work_connection(struct bufferevent *bev, uint32_t sid)
new_work_connection(struct bufferevent *bev, struct tmux_stream *stream)
{
struct bufferevent *bout = bev;
assert(bout);
assert(bev);
/* send new work session regist request to frps*/
struct work_conn *work_c = new_work_conn();
@@ -196,10 +204,8 @@ sync_new_work_connection(struct bufferevent *bev, uint32_t sid)
debug(LOG_ERR, "new work connection request run_id marshal failed!");
return;
}
tcp_mux_send_win_update_syn(bev, sid);
send_msg_frp_server(bev, TypeNewWorkConn, new_work_conn_request_message, nret, sid);
send_msg_frp_server(bev, TypeNewWorkConn, new_work_conn_request_message, nret, stream);
SAFE_FREE(new_work_conn_request_message);
SAFE_FREE(work_c);
@@ -216,7 +222,33 @@ connect_server(struct event_base *base, const char *name, const int port)
bufferevent_free(bev);
return NULL;
}
return bev;
}
struct bufferevent *
connect_udp_server(struct event_base *base)
{
evutil_socket_t fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (fd < 0) {
debug(LOG_ERR, "create udp socket failed!");
return NULL;
}
if (evutil_make_socket_nonblocking(fd) < 0) {
debug(LOG_ERR, "make udp socket nonblocking failed!");
evutil_closesocket(fd);
return NULL;
}
struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
assert(bev);
if (!bev) {
evutil_closesocket(fd);
debug(LOG_ERR, "create udp bufferevent failed!");
return NULL;
}
return bev;
}
@@ -230,32 +262,27 @@ set_ticker_ping_timer(struct event *timeout)
event_add(timeout, &tv);
}
static void
set_tcp_mux_ping_timer(struct event *timeout)
{
struct timeval tv;
evutil_timerclear(&tv);
tv.tv_sec = 60;
event_add(timeout, &tv);
}
static void
hb_sender_cb(evutil_socket_t fd, short event, void *arg)
{
debug(LOG_DEBUG, "hb_sender_cb");
if (is_client_connected()) {
debug(LOG_DEBUG, "ping frps");
debug(LOG_INFO, "ping frps");
ping(NULL);
}
set_ticker_ping_timer(main_ctl->ticker_ping);
}
struct common_conf *c_conf = get_common_config();
time_t current_time = time(NULL);
int interval = current_time - pong_time;
if (pong_time && interval > c_conf->heartbeat_timeout) {
debug(LOG_INFO, " interval [%d] greater than heartbeat_timeout [%d]", interval, c_conf->heartbeat_timeout);
static void
tcp_mux_hb_sender_cb(evutil_socket_t fd, short event, void *arg)
{
tcp_mux_send_ping(main_ctl->connect_bev, main_ctl->tcp_mux_ping_id++);
set_tcp_mux_ping_timer(main_ctl->tcp_mux_ping_event);
reset_session_id();
clear_main_control();
run_control();
return;
}
}
// return: 0: raw succeed 1: raw failed
@@ -316,7 +343,6 @@ handle_enc_msg(const uint8_t *enc_msg, int ilen, uint8_t **out)
init_main_decoder(buf);
buf += get_block_size();
ilen -= get_block_size();
debug(LOG_DEBUG, "first recv stream message, init decoder iv succeed! %d", ilen);
if (!ilen) {
// recv only iv
debug(LOG_DEBUG, "recv eas1238 iv data");
@@ -327,7 +353,6 @@ handle_enc_msg(const uint8_t *enc_msg, int ilen, uint8_t **out)
uint8_t *dec_msg = NULL;
size_t len = decrypt_data(buf, ilen, get_main_decoder(), &dec_msg);
*out = dec_msg;
debug(LOG_DEBUG, "dec out len %d ", len);
return len;
}
@@ -340,10 +365,10 @@ handle_control_work(const uint8_t *buf, int len, void *ctx)
const uint8_t *enc_msg = buf;
if (!ctx) {
debug(LOG_DEBUG, "main control message");
//debug(LOG_DEBUG, "main control message");
handle_enc_msg(enc_msg, len, &frps_cmd);
} else {
debug(LOG_DEBUG, "worker message");
//debug(LOG_DEBUG, "worker message");
frps_cmd = (uint8_t *)buf;
}
@@ -353,18 +378,18 @@ handle_control_work(const uint8_t *buf, int len, void *ctx)
struct msg_hdr *msg = (struct msg_hdr *)frps_cmd;
cmd_type = msg->type;
debug(LOG_DEBUG, "cmd_type is %c data is %s", cmd_type, msg->data);
switch(cmd_type) {
case TypeReqWorkConn:
debug(LOG_DEBUG, "TypeReqWorkConn cmd");
{
if (! is_client_connected()) {
start_proxy_services();
client_connected(1);
set_client_status(1);
}
new_client_connect();
break;
}
case TypeNewProxyResp:
debug(LOG_DEBUG, "TypeNewProxyResp cmd");
{
struct new_proxy_response *npr = new_proxy_resp_unmarshal((const char *)msg->data);
if (npr == NULL) {
debug(LOG_ERR, "new proxy response buffer unmarshal faild!");
@@ -374,8 +399,9 @@ handle_control_work(const uint8_t *buf, int len, void *ctx)
proxy_service_resp_raw(npr);
SAFE_FREE(npr);
break;
}
case TypeStartWorkConn:
debug(LOG_DEBUG, "TypeStartWorkConn cmd");
{
struct start_work_conn_resp *sr = start_work_conn_resp_unmarshal((const char *)msg->data);
if (! sr) {
debug(LOG_ERR,
@@ -410,7 +436,25 @@ handle_control_work(const uint8_t *buf, int len, void *ctx)
set_client_work_start(client, 1);
break;
}
case TypeUDPPacket:
{
struct udp_packet *udp = udp_packet_unmarshal((const char *)msg->data);
if (!udp) {
debug(LOG_ERR, "TypeUDPPacket unmarshal failed!");
break;
}
debug(LOG_DEBUG, "recv udp packet from server, content is %s",
udp->content);
assert(ctx);
struct proxy_client *client = ctx;
assert(client->ps);
handle_udp_packet(udp, client);
SAFE_FREE(udp);
break;
}
case TypePong:
pong_time = time(NULL);
break;
default:
debug(LOG_INFO, "command type dont support: ctx is %d", ctx?1:0);
@@ -459,7 +503,7 @@ handle_login_response(const uint8_t *buf, int len)
assert(nret > 0);
// start proxy services must first send
start_proxy_services();
client_connected(1);
set_client_status(1);
debug(LOG_DEBUG, "TypeReqWorkConn cmd, msg :%s", &frps_cmd[8]);
assert (frps_cmd[0] == TypeReqWorkConn);
new_client_connect();
@@ -478,6 +522,8 @@ handle_frps_msg(uint8_t *buf, int len, void *ctx)
}
}
static struct tmux_stream abandon_stream;
// ctx: if recv_cb was called by common control, ctx == NULL
// else ctx == client struct
static void
@@ -486,22 +532,109 @@ recv_cb(struct bufferevent *bev, void *ctx)
struct evbuffer *input = bufferevent_get_input(bev);
int len = evbuffer_get_length(input);
if (len <= 0) {
return;
return;
}
uint8_t *buf = calloc(len+1, 1);
assert(buf);
evbuffer_remove(input, buf, len);
struct common_conf *c_conf = get_common_config();
if (c_conf->tcp_mux) {
handle_tcp_mux_frps_msg(buf, len, handle_frps_msg);
} else {
handle_frps_msg(buf, len, ctx);
}
static struct tcp_mux_header tmux_hdr;
static uint32_t stream_len = 0;
while (len > 0) {
struct tmux_stream *cur = get_cur_stream();
size_t nr = 0;
if (!cur) {
memset(&tmux_hdr, 0, sizeof(tmux_hdr));
uint8_t *data = (uint8_t *)&tmux_hdr;
if (len < sizeof(tmux_hdr)) {
debug(LOG_INFO, "len [%d] < sizeof tmux_hdr", len);
break;
}
nr = bufferevent_read(bev, data, sizeof(tmux_hdr));
assert(nr == sizeof(tmux_hdr));
assert(validate_tcp_mux_protocol(&tmux_hdr) > 0);
len -= nr;
if (tmux_hdr.type == DATA) {
uint32_t stream_id = ntohl(tmux_hdr.stream_id);
stream_len = ntohl(tmux_hdr.length);
cur = get_stream_by_id(stream_id);
if (!cur) {
debug(LOG_INFO, "cur is NULL stream_id is %d, stream_len is %d len is %d",
stream_id, stream_len, len);
if (stream_len > 0)
cur = &abandon_stream;
else
continue;
}
if (len == 0) {
set_cur_stream(cur);
break;
}
if (len >= stream_len) {
nr = tmux_stream_read(bev, cur, stream_len);
assert(nr == stream_len);
len -= stream_len;
} else {
nr = tmux_stream_read(bev, cur, len);
stream_len -= len;
assert(nr == len);
set_cur_stream(cur);
len -= nr;
break;
}
}
} else {
assert(tmux_hdr.type == DATA);
if (len >= stream_len ) {
nr = tmux_stream_read(bev, cur, stream_len);
assert(nr == stream_len);
len -= stream_len;
} else {
nr = tmux_stream_read(bev, cur, len);
stream_len -= len;
assert(nr == len);
len -= nr;
break;
}
}
if (cur == &abandon_stream) {
debug(LOG_INFO, "abandon stream data ...");
memset(cur , 0, sizeof(abandon_stream));
set_cur_stream(NULL);
continue;
}
switch(tmux_hdr.type) {
case DATA:
case WINDOW_UPDATE:
{
handle_tcp_mux_stream(&tmux_hdr, handle_frps_msg);
break;
}
case PING:
handle_tcp_mux_ping(&tmux_hdr);
break;
case GO_AWAY:
handle_tcp_mux_go_away(&tmux_hdr);
break;
default:
debug(LOG_ERR, "impossible here!!!!");
exit(-1);
}
set_cur_stream(NULL);
}
} else {
uint8_t *buf = calloc(len, 1);
assert(buf);
evbuffer_remove(input, buf, len);
handle_frps_msg(buf, len, ctx);
SAFE_FREE(buf);
}
SAFE_FREE(buf);
return;
}
@@ -512,77 +645,43 @@ connect_event_cb (struct bufferevent *bev, short what, void *ctx)
static int retry_times = 1;
if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
if (retry_times >= 100) {
debug(LOG_ERR,
"have retry connect to xfrp server for %d times, exit!",
debug(LOG_INFO,
"have retry connect to xfrp server for %d times, exit?",
retry_times);
exit(0);
}
sleep(retry_times);
sleep(2);
retry_times++;
debug(LOG_ERR, "error: connect server [%s:%d] failed %s",
c_conf->server_addr,
c_conf->server_port,
strerror(errno));
reset_session_id();
clear_main_control();
start_base_connect();
run_control();
} else if (what & BEV_EVENT_CONNECTED) {
debug(LOG_DEBUG, "xfrp server connected");
retry_times = 0;
tcp_mux_send_win_update_syn(bev, main_ctl->stream_id);
send_window_update(bev, &main_ctl->stream, 0);
login();
keep_control_alive();
}
}
static void
keep_control_alive()
{
debug(LOG_DEBUG, "start keep_control_alive");
main_ctl->ticker_ping = evtimer_new(main_ctl->connect_base, hb_sender_cb, NULL);
if ( !main_ctl->ticker_ping) {
debug(LOG_ERR, "Ping Ticker init failed!");
return;
}
pong_time = time(NULL);
set_ticker_ping_timer(main_ctl->ticker_ping);
}
static void
keep_control_tcp_mux_alive()
{
struct common_conf *c_conf = get_common_config();
if (!c_conf->tcp_mux) return;
main_ctl->tcp_mux_ping_event = evtimer_new(main_ctl->connect_base, tcp_mux_hb_sender_cb, NULL);
assert(main_ctl->tcp_mux_ping_event);
set_tcp_mux_ping_timer(main_ctl->tcp_mux_ping_event);
}
static void
server_dns_cb(int event_code, struct evutil_addrinfo *addr, void *ctx)
{
if (event_code) {
set_common_server_ip((const char *)evutil_gai_strerror(event_code));
} else {
struct evutil_addrinfo *ai;
if (addr->ai_canonname)
debug(LOG_DEBUG, "addr->ai_canonname [%s]", addr->ai_canonname);
for (ai = addr; ai; ai = ai->ai_next) {
char buf[128];
const char *s = NULL;
if (ai->ai_family == AF_INET) {
struct sockaddr_in *sin = (struct sockaddr_in *)ai->ai_addr;
s = evutil_inet_ntop(AF_INET, &sin->sin_addr, buf, 128);
} else if (ai->ai_family == AF_INET6) {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ai->ai_addr;
s = evutil_inet_ntop(AF_INET6, &sin6->sin6_addr, buf, 128);
}
if (s) set_common_server_ip(s);
}
if (addr) evutil_freeaddrinfo(addr);
}
}
void
start_base_connect()
{
struct common_conf *c_conf = get_common_config();
@@ -614,7 +713,7 @@ login()
exit(0);
}
send_msg_frp_server(NULL, TypeLogin, lg_msg, len, 1);
send_msg_frp_server(NULL, TypeLogin, lg_msg, len, &main_ctl->stream);
SAFE_FREE(lg_msg);
}
@@ -623,7 +722,7 @@ send_msg_frp_server(struct bufferevent *bev,
const enum msg_type type,
const char *msg,
const size_t msg_len,
uint32_t sid)
struct tmux_stream *stream)
{
struct bufferevent *bout = NULL;
if (bev) {
@@ -644,9 +743,11 @@ send_msg_frp_server(struct bufferevent *bev,
req_msg->length = msg_hton((uint64_t)msg_len);
memcpy(req_msg->data, msg, msg_len);
tcp_mux_send_data(bout, sid, len);
bufferevent_write(bout, (uint8_t *)req_msg, len);
struct common_conf *c_conf = get_common_config();
if (c_conf->tcp_mux)
tmux_stream_write(bout, (uint8_t *)req_msg, len, stream);
else
bufferevent_write(bout, (uint8_t *)req_msg, len);
free(req_msg);
}
@@ -656,7 +757,7 @@ send_enc_msg_frp_server(struct bufferevent *bev,
const enum msg_type type,
const char *msg,
const size_t msg_len,
uint32_t sid)
struct tmux_stream *stream)
{
struct bufferevent *bout = NULL;
if (bev) {
@@ -666,31 +767,28 @@ send_enc_msg_frp_server(struct bufferevent *bev,
}
assert(bout);
debug(LOG_DEBUG, "send enc msg ----> [%c: %s]", type, msg);
struct msg_hdr *req_msg = calloc(msg_len+sizeof(struct msg_hdr), 1);
assert(req_msg);
req_msg->type = type;
req_msg->length = msg_hton((uint64_t)msg_len);
memcpy(req_msg->data, msg, msg_len);
struct common_conf *c_conf = get_common_config();
if (get_main_encoder() == NULL) {
debug(LOG_DEBUG, "init_main_encoder .......");
tcp_mux_send_data(bout, sid, 16);
struct frp_coder *coder = init_main_encoder();
bufferevent_write(bout, coder->iv, 16);
if (c_conf->tcp_mux)
tmux_stream_write(bout, coder->iv, 16, stream);
else
bufferevent_write(bout, coder->iv, 16);
}
uint8_t *enc_msg = NULL;
size_t olen = encrypt_data((uint8_t *)req_msg, msg_len+sizeof(struct msg_hdr), get_main_encoder(), &enc_msg);
assert(olen > 0);
debug(LOG_DEBUG, "encrypt_data length %d", olen);
tcp_mux_send_data(bout, sid, olen);
bufferevent_write(bout, enc_msg, olen);
if (c_conf->tcp_mux)
tmux_stream_write(bout, enc_msg, olen, stream);
else
bufferevent_write(bout, enc_msg, olen);
free(enc_msg);
free(req_msg);
@@ -738,7 +836,7 @@ send_new_proxy(struct proxy_service *ps)
debug(LOG_DEBUG, "control proxy client: [Type %d : proxy_name %s : msg_len %d]", TypeNewProxy, ps->proxy_name, len);
send_enc_msg_frp_server(NULL, TypeNewProxy, new_proxy_msg, len, main_ctl->stream_id);
send_enc_msg_frp_server(NULL, TypeNewProxy, new_proxy_msg, len, &main_ctl->stream);
SAFE_FREE(new_proxy_msg);
}
@@ -763,9 +861,10 @@ init_main_control()
}
main_ctl->connect_base = base;
if (c_conf->tcp_mux)
main_ctl->stream_id = get_next_session_id();
if (c_conf->tcp_mux) {
init_tmux_stream(&main_ctl->stream, get_next_session_id(), INIT);
}
// if server_addr is ip, done control init.
if (is_valid_ip_address((const char *)c_conf->server_addr))
return;
@@ -786,29 +885,6 @@ init_main_control()
evdns_base_nameserver_ip_add(dnsbase, "223.5.5.5"); //AliDNS
evdns_base_nameserver_ip_add(dnsbase, "223.6.6.6"); //AliDNS
evdns_base_nameserver_ip_add(dnsbase, "114.114.114.114"); //114DNS
// if server_addr is domain, analyze it to ip for server_ip
debug(LOG_DEBUG, "Get ip address of [%s] from DNServer", c_conf->server_addr);
struct evutil_addrinfo hints;
struct evdns_getaddrinfo_request *dns_req;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_flags = EVUTIL_AI_CANONNAME;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
dns_req = evdns_getaddrinfo(dnsbase,
c_conf->server_addr,
NULL /* no service name given */,
&hints,
server_dns_cb,
NULL);
if (!dns_req) {
debug(LOG_ERR, "error: can not analyse the dns of [%s]", c_conf->server_addr);
exit(0);
}
}
static void
@@ -825,6 +901,12 @@ clear_main_control()
if (main_ctl->ticker_ping) evtimer_del(main_ctl->ticker_ping);
if (main_ctl->tcp_mux_ping_event) evtimer_del(main_ctl->tcp_mux_ping_event);
clear_all_proxy_client();
free_evp_cipher_ctx();
set_client_status(0);
pong_time = 0;
is_login = 0;
if (get_common_config()->tcp_mux)
init_tmux_stream(&main_ctl->stream, get_next_session_id(), INIT);
}
void
@@ -843,8 +925,6 @@ void
run_control()
{
start_base_connect();
keep_control_alive();
keep_control_tcp_mux_alive();
}

View File

@@ -27,7 +27,6 @@
#ifndef _CONTROL_H_
#define _CONTROL_H_
#include "const.h"
#include "uthash.h"
#include "msg.h"
@@ -44,13 +43,11 @@ struct control {
struct event *tcp_mux_ping_event;
uint32_t tcp_mux_ping_id;
uint32_t stream_id;
struct tmux_stream stream;
};
void connect_eventcb(struct bufferevent *bev, short events, void *ptr);
void start_base_connect();
void init_main_control();
void run_control();
@@ -69,13 +66,13 @@ void send_msg_frp_server(struct bufferevent *bev,
const enum msg_type type,
const char *msg,
const size_t msg_len,
uint32_t sid);
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,
uint32_t sid);
struct tmux_stream *stream);
void control_process(struct proxy_client *client);
@@ -83,4 +80,6 @@ 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_udp_server(struct event_base *base);
#endif //_CONTROL_H_

View File

@@ -43,6 +43,46 @@ 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;
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()
@@ -51,14 +91,14 @@ get_block_size()
}
struct frp_coder *
new_coder(const char *privilege_token, const char *salt)
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->token = token ? strdup(token):strdup("\0");
enc->salt = strdup(salt);
encrypt_key(enc->privilege_token, strlen(enc->privilege_token), enc->salt, enc->key, block_size);
encrypt_key(enc->token, strlen(enc->token), enc->salt, enc->key, block_size);
encrypt_iv(enc->iv, block_size);
return enc;
}
@@ -69,7 +109,7 @@ 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->privilege_token = strdup(coder->privilege_token);
enc->token = strdup(coder->token);
enc->salt = strdup(coder->salt);
return enc;
@@ -175,11 +215,11 @@ encrypt_data(const uint8_t *src_data, size_t srclen, struct frp_coder *encoder,
assert(outbuf);
*ret = outbuf;
static EVP_CIPHER_CTX *ctx = NULL;
if (!ctx) {
ctx = EVP_CIPHER_CTX_new();
EVP_EncryptInit_ex(ctx, EVP_aes_128_cfb(), NULL, c->key, c->iv);
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!");
@@ -208,12 +248,12 @@ decrypt_data(const uint8_t *enc_data, size_t enclen, struct frp_coder *decoder,
assert(decoder);
int outlen = 0, tmplen = 0;
static EVP_CIPHER_CTX *ctx= NULL;
if (!ctx) {
ctx= EVP_CIPHER_CTX_new();
EVP_DecryptInit_ex(ctx, EVP_aes_128_cfb(), NULL, c->key, c->iv);
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;
@@ -233,7 +273,7 @@ D_END:
void
free_encoder(struct frp_coder *encoder) {
if (encoder) {
SAFE_FREE(encoder->privilege_token);
SAFE_FREE(encoder->token);
SAFE_FREE(encoder->salt);
free(encoder);
}

View File

@@ -38,7 +38,7 @@ struct frp_coder {
uint8_t key[16];
char *salt;
uint8_t iv[16];
char *privilege_token;
char *token;
};
size_t get_encrypt_block_size();
@@ -47,7 +47,7 @@ int is_encoder_inited();
int is_decoder_inited();
struct frp_coder *init_main_encoder();
struct frp_coder *init_main_decoder(const uint8_t *iv);
struct frp_coder *new_coder(const char *privilege_token, const char *salt);
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);
@@ -55,5 +55,6 @@ 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_

13
docker/Dockerfile Normal file
View 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 .

View File

@@ -89,7 +89,6 @@ void init_login()
c_login->metas = NULL;
c_login->pool_count = 1;
c_login->privilege_key = NULL;
c_login->user = c_conf->user;
c_login->logged = 0;
@@ -100,7 +99,7 @@ void init_login()
exit(0);
}
if (strcmp(ifname, "br-lan") == 0) {
if (strcmp(ifname, "br-lan") == 0 || strcmp(ifname, "br0") == 0) {
c_conf->is_router = 1;
debug(LOG_DEBUG, "working in router");
}

176
msg.c
View File

@@ -34,7 +34,6 @@
#include <netinet/in.h>
#include "msg.h"
#include "const.h"
#include "config.h"
#include "debug.h"
#include "common.h"
@@ -174,15 +173,37 @@ new_proxy_service_marshal(const struct proxy_service *np_req, char **msg)
{
const char *tmp = NULL;
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)
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);
// 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);
}
@@ -204,6 +225,11 @@ 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);
}
@@ -268,8 +294,7 @@ new_proxy_resp_unmarshal(const char *jres)
if (port) {
port++;
npr->remote_port = atoi(port);
}else
goto END_ERROR;
}
struct json_object *npr_proxy_name = NULL;
if (! json_object_object_get_ex(j_np_res, "proxy_name", &npr_proxy_name))
@@ -402,3 +427,146 @@ get_msg_type(uint8_t type)
return NULL;
}
// marshal udp packet msg
int
new_udp_packet_marshal(const struct udp_packet *udp, char **msg)
{
// 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;
}
void
udp_packet_free(struct udp_packet *udp)
{
if (!udp)
return;
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);
SAFE_FREE(udp);
}
// unmarshal udp packet msg
struct udp_packet *
udp_packet_unmarshal (const char *msg)
{
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);
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);
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);
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;
}

18
msg.h
View File

@@ -86,6 +86,18 @@ struct work_conn {
char *run_id;
};
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;
@@ -96,6 +108,7 @@ 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);
char *calc_md5(const char *data, int datalen);
@@ -112,6 +125,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);
char *get_msg_type(uint8_t type);

View File

@@ -1,54 +0,0 @@
#
# Copyright (C) 2022 Dengfeng Liu
#
# This is free software, licensed under the GNU General Public License v3.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=xfrpc
PKG_VERSION:=master
PKG_RELEASE:=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/liudf0716/xfrpc.git
PKG_SOURCE_VERSION:=$(PKG_VERSION)
PKG_MIRROR_HASH:=a7141da8a85203d8341fd6d2551f1228396ae54aace6ec0bad2dfeb89e0a377d
PKG_MAINTAINER:=Dengfeng Liu <liudf0716@gmail.com>
PKG_LICENSE:=GPL-3.0-or-later
PKG_LICENSE_FILES:=COPYING
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk
define Package/xfrpc
SUBMENU:=Web Servers/Proxies
SECTION:=net
CATEGORY:=Network
DEPENDS:=+zlib +libjson-c +libevent2 +libevent2-openssl
TITLE:= C language fast reverse proxy client
URL:=https://github.com/liudf0716/xfrpc
endef
define Package/xfrpc/description
xfrpc is C language fast reverse proxy client
compare with golang version frpc
xfrpc can run in almost all openwrt device
endef
define Package/xfrpc/conffiles
/etc/config/xfrpc
endef
define Package/xfrpc/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/xfrpc $(1)/usr/bin/xfrpc
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/xfrpc.init $(1)/etc/init.d/xfrpc
$(INSTALL_DIR) $(1)/etc/config
$(CP) ./files/xfrpc.conf $(1)/etc/config/xfrpc
endef
$(eval $(call BuildPackage,xfrpc))

View File

@@ -1,26 +0,0 @@
config xfrp 'init'
option disabled 1
option loglevel 7
config xfrpc 'common'
option server_addr 127.0.0.1
option server_port 7000
option token abdesf13d
config xfrpc 'ssh01'
option type tcp
option local_ip 127.0.0.1
option local_port 22
option remote_port 6000
#config xfrpc 'web01'
# option type http
# option local_ip 127.0.0.1
# option local_port 8080
# option custom_domains yourdomain
#config xfrpc 'web02'
# option type https
# option local_ip 127.0.0.1
# option local_port 8443
# option custom_domains yourdomain

View File

@@ -1,93 +0,0 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2022 Dengfeng Liu <liu_df@qq.com>
#
# This is free software, licensed under the GNU General Public License v3.
# See /LICENSE for more information.
#
START=99
USE_PROCD=1
NAME=xfrpc
PROG=/usr/bin/$NAME
handle_xfrpc() {
local name="$1"
local config="$2"
echo "[$name]" >> "$config"
handle_type() {
uci_validate_section xfrpc xfrpc "$name" \
'type:or("tcp", "udp", "ftp", "http", "https")' \
'local_ip:ipaddr:127.0.0.1' \
'local_port:uinteger'
echo "type = $type" >> "$config"
echo "local_ip = $local_ip" >> "$config"
echo "local_port = $local_port" >> "$config"
case "$type" in
"tcp"|"udp")
config_get remote_port "$name" remote_port
echo "remote_port = $remote_port" >> "$config"
;;
"ftp")
config_get remote_port "$name" remote_port
config_get remote_data_port "$name" remote_data_port
echo "remote_port = $remote_port" >> "$config"
echo "remote_data_port = $remote_data_port" >> "$config"
;;
esac
}
if [ "$name" = "common" ]; then
uci_validate_section xfrpc xfrpc "$name" \
'server_addr:ipaddr' \
'server_port:uinteger' \
'token:string'
[ -z "$token" ] && {
echo "no token"
exit
}
echo "server_addr = $server_addr" >> "$config"
echo "server_port = $server_port" >> "$config"
echo "token = $token" >> "$config"
else
handle_type
fi
}
service_triggers() {
procd_add_reload_trigger "$NAME"
}
start_service() {
local conf_file="/var/etc/$NAME.ini"
> "$conf_file"
config_load "$NAME"
uci_validate_section xfrpc xfrpc init \
'disabled:bool:1' \
'loglevel:uinteger:0'
if [ $disabled = 1 ]; then
echo "xfrpc service disabled"
return
fi
config_foreach handle_xfrpc xfrpc "$conf_file"
procd_open_instance
procd_set_param command "$PROG" -c "$conf_file" -f -d $loglevel
procd_set_param file "$conf_file"
procd_set_param respawn
procd_close_instance
}
reload_service() {
stop
start
}

12
pkg/debian/rules Normal file
View 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 $@

615
plugins/telnetd.c Normal file
View 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
View 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

11
proxy.h
View File

@@ -36,6 +36,8 @@
#include "client.h"
#include "common.h"
#include "tcpmux.h"
#include "msg.h"
#define IP_LEN 16
@@ -55,9 +57,18 @@ 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_

View File

@@ -101,12 +101,12 @@ void ftp_proxy_c2s_cb(struct bufferevent *bev, void *ctx)
struct ftp_pasv *r_fp = new_ftp_pasv();
r_fp->code = local_fp->code;
if (! c_conf->server_ip) {
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_ip, IP_LEN);
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) {
@@ -264,4 +264,4 @@ static void free_ftp_pasv(struct ftp_pasv *fp)
SAFE_FREE(fp);
fp = NULL;
}
}

View File

@@ -34,6 +34,7 @@
#include <errno.h>
#include <syslog.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
@@ -46,8 +47,221 @@
#include "proxy.h"
#include "config.h"
#include "tcpmux.h"
#include "control.h"
#define BUF_LEN 4096
#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)
@@ -66,24 +280,18 @@ void tcp_proxy_c2s_cb(struct bufferevent *bev, void *ctx)
return;
}
if (client->send_window == 0) {
debug(LOG_DEBUG, "client %d recv len %d exceed send windows: %d", client->stream_id, len, client->send_window);
bufferevent_disable(bev, EV_READ);
return;
} else {
len = client->send_window>=len?len:client->send_window;
client->send_window -= len;
}
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);
tcp_mux_send_data(partner, client->stream_id, len);
uint8_t buf[BUF_LEN];
while(len > 0) {
memset(buf, 0, BUF_LEN);
int nread = bufferevent_read(bev, buf, len>BUF_LEN?BUF_LEN:len);
assert(nread >= 0);
bufferevent_write(partner, buf, nread);
len -= nread;
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

220
proxy_udp.c Normal file
View 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);
}

211
tcp_redir.c Normal file
View 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
View 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

767
tcpmux.c
View File

@@ -24,71 +24,96 @@
@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;
static struct tcp_mux_type_desc type_desc[] = {
{DATA, "data"},
{WINDOW_UPDATE, "window update"},
{PING, "ping"},
{GO_AWAY, "go away"},
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);
};
static struct tcp_mux_flag_desc flag_desc[] = {
{ZERO, "zero"},
{SYN, "syn"},
{ACK, "ack"},
{FIN, "fin"},
{RST, "rst"},
};
static const char *
type_2_desc(enum tcp_mux_type type)
int
validate_tcp_mux_protocol(struct tcp_mux_header *tmux_hdr)
{
for(int i = 0; i < sizeof(type_desc)/sizeof(struct tcp_mux_type_desc); i++){
if (type == type_desc[i].type)
return type_desc[i].desc;
}
return "unkown_type";
}
static const char *
flag_2_desc(enum tcp_mux_flag flag)
{
for(int i = 0; i < sizeof(flag_desc)/sizeof(struct tcp_mux_flag_desc); i++){
if (flag == flag_desc[i].flag)
return flag_desc[i].desc;
}
if (tmux_hdr->version != proto_version) return 0;
return "unkown_flag";
if (tmux_hdr->type > GO_AWAY) return 0;
return 1;
}
static int
valid_tcp_mux_type(uint8_t type)
{
if (type >= DATA && type <= GO_AWAY)
return 1;
return 0;
}
static int
valid_tcp_mux_sid(uint32_t sid)
{
if (sid == 1)
return 1;
return get_proxy_client(sid)?1:0;
}
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)
{
@@ -107,65 +132,33 @@ tcp_mux_flag()
return c_conf->tcp_mux;
}
static void
dump_tcp_mux_header(uint8_t *data, int len)
{
if (len != 12)
return;
printf("tcp mux header is : \n");
for (int i = 0; i < len; i++)
printf("%2x", data[i]);
printf("\n");
}
static uint32_t
parse_tcp_mux_proto(uint8_t *data, int len, uint32_t *flag, uint32_t *type, uint32_t *stream_id, uint32_t *dlen)
{
struct common_conf *c_conf = get_common_config();
if (!c_conf->tcp_mux)
return 0;
if (len < sizeof(struct tcp_mux_header))
return 0;
struct tcp_mux_header *hdr = (struct tcp_mux_header *)data;
if(hdr->version == proto_version &&
valid_tcp_mux_type(hdr->type)) {
if (hdr->type == DATA && !valid_tcp_mux_sid(htonl(hdr->stream_id))) {
debug(LOG_INFO, "!!!!!type is DATA but cant find stream_id : type [%s] flag [%s] stream_id[%d]",
type_2_desc(hdr->type), flag_2_desc(htons(hdr->flags)), htonl(hdr->stream_id));
dump_tcp_mux_header(data, len);
exit(-1);
}
*type = hdr->type;
*flag = htons(hdr->flags);
*stream_id = htonl(hdr->stream_id);
*dlen = htonl(hdr->length);
return 1;
}
return 0;
void
reset_session_id() {
g_session_id = 1;
}
uint32_t
get_next_session_id() {
static uint32_t next_session_id = 1;
uint32_t id = next_session_id;
next_session_id += 2;
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;
struct tcp_mux_header tmux_hdr;
memset(&tmux_hdr, 0, sizeof(tmux_hdr));
tcp_mux_encode(WINDOW_UPDATE, SYN, stream_id, 0, &tmux_hdr);
debug(LOG_DEBUG, "tcp mux [%d] send wind update syn", stream_id);
bufferevent_write(bout, (uint8_t *)&tmux_hdr, sizeof(tmux_hdr));
tcp_mux_send_win_update(bout, SYN, stream_id, 0);
}
void
@@ -173,11 +166,7 @@ tcp_mux_send_win_update_ack(struct bufferevent *bout, uint32_t stream_id, uint32
{
if (!tcp_mux_flag()) return;
struct tcp_mux_header tmux_hdr;
memset(&tmux_hdr, 0, sizeof(tmux_hdr));
tcp_mux_encode(WINDOW_UPDATE, ZERO, stream_id, delta, &tmux_hdr);
debug(LOG_DEBUG, "tcp mux [%d] send wind update ZERO [%d]", stream_id, delta);
bufferevent_write(bout, (uint8_t *)&tmux_hdr, sizeof(tmux_hdr));
tcp_mux_send_win_update(bout, ZERO, stream_id, 0);
}
void
@@ -185,21 +174,24 @@ tcp_mux_send_win_update_fin(struct bufferevent *bout, uint32_t stream_id)
{
if (!tcp_mux_flag()) return;
struct tcp_mux_header tmux_hdr;
memset(&tmux_hdr, 0, sizeof(tmux_hdr));
tcp_mux_encode(WINDOW_UPDATE, FIN, stream_id, 0, &tmux_hdr);
debug(LOG_DEBUG, "tcp mux [%d] send wind update FIN", stream_id);
bufferevent_write(bout, (uint8_t *)&tmux_hdr, sizeof(tmux_hdr));
tcp_mux_send_win_update(bout, FIN, stream_id, 0);
}
void
tcp_mux_send_data(struct bufferevent *bout, uint32_t stream_id, uint32_t length)
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, ZERO, stream_id, length, &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));
}
@@ -228,141 +220,440 @@ tcp_mux_handle_ping(struct bufferevent *bout, uint32_t ping_id)
bufferevent_write(bout, (uint8_t *)&tmux_hdr, sizeof(tmux_hdr));
}
void
handle_tcp_mux_frps_msg(uint8_t *buf, int ilen, void (*fn)(uint8_t *, int, void *))
static void
tcp_mux_send_go_away(struct bufferevent *bout, uint32_t reason)
{
static uint32_t l_stream_id = 0;
static uint32_t l_dlen = 0;
static uint32_t l_type = 0;
static uint32_t l_flag = 0;
uint8_t *data = buf;
while (ilen > 0) {
uint32_t type = 0, stream_id = 0, dlen = 0, flag = 0;
uint32_t is_tmux = parse_tcp_mux_proto(data, ilen, &flag, &type, &stream_id, &dlen);
if (!is_tmux) {
struct proxy_client *pc = get_proxy_client(l_stream_id);
debug(LOG_DEBUG, "receive only %s data : l_stream_id %d l_type %s l_flag %s l_dlen %d ilen %d",
!pc?"main control ":"worker ",
l_stream_id, type_2_desc(l_type),
flag_2_desc(l_flag), l_dlen, ilen);
assert(ilen);
if (ilen == 12)
dump_tcp_mux_header(data, ilen);
if (!tcp_mux_flag()) return;
if (!pc || (pc && !pc->local_proxy_bev)) {
assert(ilen >= l_dlen);
assert(l_dlen > 0);
fn(data, l_dlen, pc);
data += l_dlen;
ilen -= l_dlen;
l_dlen = 0;
continue;
}
if (pc->stream_state != ESTABLISHED) {
debug(LOG_INFO, "client [%d] state is [%d]", pc->stream_id, pc->stream_state);
break;
}
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));
if ( ilen >= l_dlen) {
assert(pc->local_proxy_bev);
bufferevent_write(pc->local_proxy_bev, data, l_dlen);
data += l_dlen;
ilen -= l_dlen;
l_dlen = 0;
} else {
assert(pc->local_proxy_bev);
bufferevent_write(pc->local_proxy_bev, data, ilen);
l_dlen -= ilen;
ilen = 0;
}
}
continue;
}
struct proxy_client *pc = get_proxy_client(stream_id);
debug(LOG_DEBUG, "[%s] receive tcp mux type [%s] flag [%s] stream_id [%d] dlen [%d] ilen [%d]",
pc?"worker":"main control",
type_2_desc(type), flag_2_desc(flag), stream_id, dlen, ilen);
data += sizeof(struct tcp_mux_header);
ilen -= sizeof(struct tcp_mux_header);
l_stream_id = stream_id;
l_type = type;
l_flag = flag;
l_dlen = type==PING?0:dlen;
assert(ilen >= 0);
switch(type) {
case DATA:
{
if (ilen == 0)
break;
if (!pc || (pc && !pc->local_proxy_bev)) {
assert(ilen >= dlen);
fn(data, dlen, pc);
data += dlen;
ilen -= dlen;
l_dlen = 0;
continue;
}
if (pc->stream_state != ESTABLISHED) {
debug(LOG_INFO, "client [%d] state is [%d]", pc->stream_id, pc->stream_state);
break;
}
if (ilen >= dlen){
assert(pc->local_proxy_bev);
bufferevent_write(pc->local_proxy_bev, data, dlen);
data += dlen;
ilen -= dlen;
l_dlen = 0;
} else {
assert(pc->local_proxy_bev);
bufferevent_write(pc->local_proxy_bev, data, ilen);
l_dlen -= ilen;
ilen = 0;
}
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 PING:
{
struct bufferevent *bout = get_main_control()->connect_bev;
uint32_t seq = dlen;
assert(bout);
if (flag == SYN)
tcp_mux_handle_ping(bout, seq);
case LOCAL_CLOSE:
stream->state = CLOSED;
close_stream = 1;
break;
}
case WINDOW_UPDATE:
{
switch(flag) {
case RST:
case FIN:
del_proxy_client(pc);
break;
case ZERO:
case ACK:
if (!pc)
break;
if (dlen > 0) {
pc->send_window += dlen;
bufferevent_enable(pc->local_proxy_bev, EV_READ|EV_WRITE);
}
pc->stream_state = ESTABLISHED;
break;
default:
debug(LOG_INFO, "window update no need process : flag %2x %s dlen %d stream_id %d",
flag, flag_2_desc(flag), dlen, stream_id);
}
break;
}
default:
debug(LOG_INFO, "no need unhandle tcp mux msg : type %s flag %s stream_id %d dlen %d ilen %d",
type_2_desc(type), flag_2_desc(flag), stream_id, dlen, ilen);
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;
}

View File

@@ -29,6 +29,24 @@
#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,
@@ -73,20 +91,73 @@ enum tcp_mux_state {
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_data(struct bufferevent *bout, uint32_t stream_id, uint32_t length);
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);
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);
void handle_tcp_mux_frps_msg(uint8_t *data, int len, void (*fn)(uint8_t *, int, void *));
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
View 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
View 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
View 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
View 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

View 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

View File

@@ -0,0 +1,2 @@
/* Define to 1 if you have the <inttypes.h> header file. */
#define JSON_C_HAVE_INTTYPES_H 1

View 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

File diff suppressed because it is too large Load Diff

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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_ */

File diff suppressed because it is too large Load Diff

View 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

File diff suppressed because it is too large Load Diff

View 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

View 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_ */

View 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
View 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_ */

View 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_ */

View 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_ */

View 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

File diff suppressed because it is too large Load Diff

View 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_ */

View 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

File diff suppressed because it is too large Load Diff

View 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_ */

View 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_ */

View 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

View 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
View 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_ */

View 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_ */

View File

@@ -0,0 +1,114 @@
/*
* 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_STRUCT_H_INCLUDED_
#define EVENT2_RPC_STRUCT_H_INCLUDED_
#ifdef __cplusplus
extern "C" {
#endif
/** @file event2/rpc_struct.h
Structures used by rpc.h. Using these structures directly may harm
forward compatibility: be careful!
*/
/* 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 */
/**
* provides information about the completed RPC request.
*/
struct evrpc_status {
#define EVRPC_STATUS_ERR_NONE 0
#define EVRPC_STATUS_ERR_TIMEOUT 1
#define EVRPC_STATUS_ERR_BADPAYLOAD 2
#define EVRPC_STATUS_ERR_UNSTARTED 3
#define EVRPC_STATUS_ERR_HOOKABORTED 4
int error;
/* for looking at headers or other information */
struct evhttp_request *http_req;
};
/* the structure below needs to be synchronized with evrpc_req_generic */
/* Encapsulates a request */
struct evrpc {
TAILQ_ENTRY(evrpc) next;
/* the URI at which the request handler lives */
const char* uri;
/* creates a new request structure */
void *(*request_new)(void *);
void *request_new_arg;
/* frees the request structure */
void (*request_free)(void *);
/* unmarshals the buffer into the proper request structure */
int (*request_unmarshal)(void *, struct evbuffer *);
/* creates a new reply structure */
void *(*reply_new)(void *);
void *reply_new_arg;
/* frees the reply structure */
void (*reply_free)(void *);
/* verifies that the reply is valid */
int (*reply_complete)(void *);
/* marshals the reply into a buffer */
void (*reply_marshal)(struct evbuffer*, void *);
/* the callback invoked for each received rpc */
void (*cb)(struct evrpc_req_generic *, void *);
void *cb_arg;
/* reference for further configuration */
struct evrpc_base *base;
};
#ifdef EVENT_DEFINED_TQENTRY_
#undef TAILQ_ENTRY
#endif
#ifdef __cplusplus
}
#endif
#endif /* EVENT2_RPC_STRUCT_H_INCLUDED_ */

146
thirdparty/include/libevent/event2/tag.h vendored Normal file
View File

@@ -0,0 +1,146 @@
/*
* 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_TAG_H_INCLUDED_
#define EVENT2_TAG_H_INCLUDED_
/** @file event2/tag.h
Helper functions for reading and writing tagged data onto buffers.
*/
#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>
struct evbuffer;
/*
* Marshaling tagged data - We assume that all tags are inserted in their
* numeric order - so that unknown tags will always be higher than the
* known ones - and we can just ignore the end of an event buffer.
*/
EVENT2_EXPORT_SYMBOL
void evtag_init(void);
/**
Unmarshals the header and returns the length of the payload
@param evbuf the buffer from which to unmarshal data
@param ptag a pointer in which the tag id is being stored
@returns -1 on failure or the number of bytes in the remaining payload.
*/
EVENT2_EXPORT_SYMBOL
int evtag_unmarshal_header(struct evbuffer *evbuf, ev_uint32_t *ptag);
EVENT2_EXPORT_SYMBOL
void evtag_marshal(struct evbuffer *evbuf, ev_uint32_t tag, const void *data,
ev_uint32_t len);
EVENT2_EXPORT_SYMBOL
void evtag_marshal_buffer(struct evbuffer *evbuf, ev_uint32_t tag,
struct evbuffer *data);
/**
Encode an integer and store it in an evbuffer.
We encode integers by nybbles; the first nibble contains the number
of significant nibbles - 1; this allows us to encode up to 64-bit
integers. This function is byte-order independent.
@param evbuf evbuffer to store the encoded number
@param number a 32-bit integer
*/
EVENT2_EXPORT_SYMBOL
void evtag_encode_int(struct evbuffer *evbuf, ev_uint32_t number);
EVENT2_EXPORT_SYMBOL
void evtag_encode_int64(struct evbuffer *evbuf, ev_uint64_t number);
EVENT2_EXPORT_SYMBOL
void evtag_marshal_int(struct evbuffer *evbuf, ev_uint32_t tag,
ev_uint32_t integer);
EVENT2_EXPORT_SYMBOL
void evtag_marshal_int64(struct evbuffer *evbuf, ev_uint32_t tag,
ev_uint64_t integer);
EVENT2_EXPORT_SYMBOL
void evtag_marshal_string(struct evbuffer *buf, ev_uint32_t tag,
const char *string);
EVENT2_EXPORT_SYMBOL
void evtag_marshal_timeval(struct evbuffer *evbuf, ev_uint32_t tag,
struct timeval *tv);
EVENT2_EXPORT_SYMBOL
int evtag_unmarshal(struct evbuffer *src, ev_uint32_t *ptag,
struct evbuffer *dst);
EVENT2_EXPORT_SYMBOL
int evtag_peek(struct evbuffer *evbuf, ev_uint32_t *ptag);
EVENT2_EXPORT_SYMBOL
int evtag_peek_length(struct evbuffer *evbuf, ev_uint32_t *plength);
EVENT2_EXPORT_SYMBOL
int evtag_payload_length(struct evbuffer *evbuf, ev_uint32_t *plength);
EVENT2_EXPORT_SYMBOL
int evtag_consume(struct evbuffer *evbuf);
EVENT2_EXPORT_SYMBOL
int evtag_unmarshal_int(struct evbuffer *evbuf, ev_uint32_t need_tag,
ev_uint32_t *pinteger);
EVENT2_EXPORT_SYMBOL
int evtag_unmarshal_int64(struct evbuffer *evbuf, ev_uint32_t need_tag,
ev_uint64_t *pinteger);
EVENT2_EXPORT_SYMBOL
int evtag_unmarshal_fixed(struct evbuffer *src, ev_uint32_t need_tag,
void *data, size_t len);
EVENT2_EXPORT_SYMBOL
int evtag_unmarshal_string(struct evbuffer *evbuf, ev_uint32_t need_tag,
char **pstring);
EVENT2_EXPORT_SYMBOL
int evtag_unmarshal_timeval(struct evbuffer *evbuf, ev_uint32_t need_tag,
struct timeval *ptv);
#ifdef __cplusplus
}
#endif
#endif /* EVENT2_TAG_H_INCLUDED_ */

View File

@@ -0,0 +1,49 @@
/*
* 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_TAG_COMPAT_H_INCLUDED_
#define EVENT2_TAG_COMPAT_H_INCLUDED_
/** @file event2/tag_compat.h
Obsolete/deprecated functions from tag.h; provided only for backwards
compatibility.
*/
/**
@name Misnamed functions
@deprecated These macros are deprecated because their names don't follow
Libevent's naming conventions. Use evtag_encode_int and
evtag_encode_int64 instead.
@{
*/
#define encode_int(evbuf, number) evtag_encode_int((evbuf), (number))
#define encode_int64(evbuf, number) evtag_encode_int64((evbuf), (number))
/**@}*/
#endif /* EVENT2_TAG_H_INCLUDED_ */

View File

@@ -0,0 +1,253 @@
/*
* Copyright (c) 2008-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_THREAD_H_INCLUDED_
#define EVENT2_THREAD_H_INCLUDED_
/** @file event2/thread.h
Functions for multi-threaded applications using Libevent.
When using a multi-threaded application in which multiple threads
add and delete events from a single event base, Libevent needs to
lock its data structures.
Like the memory-management function hooks, all of the threading functions
_must_ be set up before an event_base is created if you want the base to
use them.
Most programs will either be using Windows threads or Posix threads. You
can configure Libevent to use one of these event_use_windows_threads() or
event_use_pthreads() respectively. If you're using another threading
library, you'll need to configure threading functions manually using
evthread_set_lock_callbacks() and evthread_set_condition_callbacks().
*/
#include <event2/visibility.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <event2/event-config.h>
/**
@name Flags passed to lock functions
@{
*/
/** A flag passed to a locking callback when the lock was allocated as a
* read-write lock, and we want to acquire or release the lock for writing. */
#define EVTHREAD_WRITE 0x04
/** A flag passed to a locking callback when the lock was allocated as a
* read-write lock, and we want to acquire or release the lock for reading. */
#define EVTHREAD_READ 0x08
/** A flag passed to a locking callback when we don't want to block waiting
* for the lock; if we can't get the lock immediately, we will instead
* return nonzero from the locking callback. */
#define EVTHREAD_TRY 0x10
/**@}*/
#if !defined(EVENT__DISABLE_THREAD_SUPPORT) || defined(EVENT_IN_DOXYGEN_)
#define EVTHREAD_LOCK_API_VERSION 1
/**
@name Types of locks
@{*/
/** A recursive lock is one that can be acquired multiple times at once by the
* same thread. No other process can allocate the lock until the thread that
* has been holding it has unlocked it as many times as it locked it. */
#define EVTHREAD_LOCKTYPE_RECURSIVE 1
/* A read-write lock is one that allows multiple simultaneous readers, but
* where any one writer excludes all other writers and readers. */
#define EVTHREAD_LOCKTYPE_READWRITE 2
/**@}*/
/** This structure describes the interface a threading library uses for
* locking. It's used to tell evthread_set_lock_callbacks() how to use
* locking on this platform.
*/
struct evthread_lock_callbacks {
/** The current version of the locking API. Set this to
* EVTHREAD_LOCK_API_VERSION */
int lock_api_version;
/** Which kinds of locks does this version of the locking API
* support? A bitfield of EVTHREAD_LOCKTYPE_RECURSIVE and
* EVTHREAD_LOCKTYPE_READWRITE.
*
* (Note that RECURSIVE locks are currently mandatory, and
* READWRITE locks are not currently used.)
**/
unsigned supported_locktypes;
/** Function to allocate and initialize new lock of type 'locktype'.
* Returns NULL on failure. */
void *(*alloc)(unsigned locktype);
/** Funtion to release all storage held in 'lock', which was created
* with type 'locktype'. */
void (*free)(void *lock, unsigned locktype);
/** Acquire an already-allocated lock at 'lock' with mode 'mode'.
* Returns 0 on success, and nonzero on failure. */
int (*lock)(unsigned mode, void *lock);
/** Release a lock at 'lock' using mode 'mode'. Returns 0 on success,
* and nonzero on failure. */
int (*unlock)(unsigned mode, void *lock);
};
/** Sets a group of functions that Libevent should use for locking.
* For full information on the required callback API, see the
* documentation for the individual members of evthread_lock_callbacks.
*
* Note that if you're using Windows or the Pthreads threading library, you
* probably shouldn't call this function; instead, use
* evthread_use_windows_threads() or evthread_use_posix_threads() if you can.
*/
EVENT2_EXPORT_SYMBOL
int evthread_set_lock_callbacks(const struct evthread_lock_callbacks *);
#define EVTHREAD_CONDITION_API_VERSION 1
struct timeval;
/** This structure describes the interface a threading library uses for
* condition variables. It's used to tell evthread_set_condition_callbacks
* how to use locking on this platform.
*/
struct evthread_condition_callbacks {
/** The current version of the conditions API. Set this to
* EVTHREAD_CONDITION_API_VERSION */
int condition_api_version;
/** Function to allocate and initialize a new condition variable.
* Returns the condition variable on success, and NULL on failure.
* The 'condtype' argument will be 0 with this API version.
*/
void *(*alloc_condition)(unsigned condtype);
/** Function to free a condition variable. */
void (*free_condition)(void *cond);
/** Function to signal a condition variable. If 'broadcast' is 1, all
* threads waiting on 'cond' should be woken; otherwise, only on one
* thread is worken. Should return 0 on success, -1 on failure.
* This function will only be called while holding the associated
* lock for the condition.
*/
int (*signal_condition)(void *cond, int broadcast);
/** Function to wait for a condition variable. The lock 'lock'
* will be held when this function is called; should be released
* while waiting for the condition to be come signalled, and
* should be held again when this function returns.
* If timeout is provided, it is interval of seconds to wait for
* the event to become signalled; if it is NULL, the function
* should wait indefinitely.
*
* The function should return -1 on error; 0 if the condition
* was signalled, or 1 on a timeout. */
int (*wait_condition)(void *cond, void *lock,
const struct timeval *timeout);
};
/** Sets a group of functions that Libevent should use for condition variables.
* For full information on the required callback API, see the
* documentation for the individual members of evthread_condition_callbacks.
*
* Note that if you're using Windows or the Pthreads threading library, you
* probably shouldn't call this function; instead, use
* evthread_use_windows_threads() or evthread_use_pthreads() if you can.
*/
EVENT2_EXPORT_SYMBOL
int evthread_set_condition_callbacks(
const struct evthread_condition_callbacks *);
/**
Sets the function for determining the thread id.
@param base the event base for which to set the id function
@param id_fn the identify function Libevent should invoke to
determine the identity of a thread.
*/
EVENT2_EXPORT_SYMBOL
void evthread_set_id_callback(
unsigned long (*id_fn)(void));
#if (defined(_WIN32) && !defined(EVENT__DISABLE_THREAD_SUPPORT)) || defined(EVENT_IN_DOXYGEN_)
/** Sets up Libevent for use with Windows builtin locking and thread ID
functions. Unavailable if Libevent is not built for Windows.
@return 0 on success, -1 on failure. */
EVENT2_EXPORT_SYMBOL
int evthread_use_windows_threads(void);
/**
Defined if Libevent was built with support for evthread_use_windows_threads()
*/
#define EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED 1
#endif
#if defined(EVENT__HAVE_PTHREADS) || defined(EVENT_IN_DOXYGEN_)
/** Sets up Libevent for use with Pthreads locking and thread ID functions.
Unavailable if Libevent is not build for use with pthreads. Requires
libraries to link against Libevent_pthreads as well as Libevent.
@return 0 on success, -1 on failure. */
EVENT2_EXPORT_SYMBOL
int evthread_use_pthreads(void);
/** Defined if Libevent was built with support for evthread_use_pthreads() */
#define EVTHREAD_USE_PTHREADS_IMPLEMENTED 1
#endif
/** Enable debugging wrappers around the current lock callbacks. If Libevent
* makes one of several common locking errors, exit with an assertion failure.
*
* If you're going to call this function, you must do so before any locks are
* allocated.
**/
EVENT2_EXPORT_SYMBOL
void evthread_enable_lock_debugging(void);
/* Old (misspelled) version: This is deprecated; use
* evthread_enable_log_debugging instead. */
EVENT2_EXPORT_SYMBOL
void evthread_enable_lock_debuging(void);
#endif /* EVENT__DISABLE_THREAD_SUPPORT */
struct event_base;
/** Make sure it's safe to tell an event base to wake up from another thread
or a signal handler.
You shouldn't need to call this by hand; configuring the base with thread
support should be necessary and sufficient.
@return 0 on success, -1 on failure.
*/
EVENT2_EXPORT_SYMBOL
int evthread_make_base_notifiable(struct event_base *base);
#ifdef __cplusplus
}
#endif
#endif /* EVENT2_THREAD_H_INCLUDED_ */

View File

@@ -0,0 +1,888 @@
/*
* 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_UTIL_H_INCLUDED_
#define EVENT2_UTIL_H_INCLUDED_
/** @file event2/util.h
Common convenience functions for cross-platform portability and
related socket manipulations.
*/
#include <event2/visibility.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <event2/event-config.h>
#ifdef EVENT__HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef EVENT__HAVE_STDINT_H
#include <stdint.h>
#elif defined(EVENT__HAVE_INTTYPES_H)
#include <inttypes.h>
#endif
#ifdef EVENT__HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef EVENT__HAVE_STDDEF_H
#include <stddef.h>
#endif
#ifdef _MSC_VER
#include <BaseTsd.h>
#endif
#include <stdarg.h>
#ifdef EVENT__HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef _WIN32
#include <winsock2.h>
#ifdef EVENT__HAVE_GETADDRINFO
/* for EAI_* definitions. */
#include <ws2tcpip.h>
#endif
#else
#ifdef EVENT__HAVE_ERRNO_H
#include <errno.h>
#endif
#include <sys/socket.h>
#endif
#include <time.h>
/* Some openbsd autoconf versions get the name of this macro wrong. */
#if defined(EVENT__SIZEOF_VOID__) && !defined(EVENT__SIZEOF_VOID_P)
#define EVENT__SIZEOF_VOID_P EVENT__SIZEOF_VOID__
#endif
/**
* @name Standard integer types.
*
* Integer type definitions for types that are supposed to be defined in the
* C99-specified stdint.h. Shamefully, some platforms do not include
* stdint.h, so we need to replace it. (If you are on a platform like this,
* your C headers are now over 10 years out of date. You should bug them to
* do something about this.)
*
* We define:
*
* <dl>
* <dt>ev_uint64_t, ev_uint32_t, ev_uint16_t, ev_uint8_t</dt>
* <dd>unsigned integer types of exactly 64, 32, 16, and 8 bits
* respectively.</dd>
* <dt>ev_int64_t, ev_int32_t, ev_int16_t, ev_int8_t</dt>
* <dd>signed integer types of exactly 64, 32, 16, and 8 bits
* respectively.</dd>
* <dt>ev_uintptr_t, ev_intptr_t</dt>
* <dd>unsigned/signed integers large enough
* to hold a pointer without loss of bits.</dd>
* <dt>ev_ssize_t</dt>
* <dd>A signed type of the same size as size_t</dd>
* <dt>ev_off_t</dt>
* <dd>A signed type typically used to represent offsets within a
* (potentially large) file</dd>
*
* @{
*/
#ifdef EVENT__HAVE_UINT64_T
#define ev_uint64_t uint64_t
#define ev_int64_t int64_t
#elif defined(_WIN32)
#define ev_uint64_t unsigned __int64
#define ev_int64_t signed __int64
#elif EVENT__SIZEOF_LONG_LONG == 8
#define ev_uint64_t unsigned long long
#define ev_int64_t long long
#elif EVENT__SIZEOF_LONG == 8
#define ev_uint64_t unsigned long
#define ev_int64_t long
#elif defined(EVENT_IN_DOXYGEN_)
#define ev_uint64_t ...
#define ev_int64_t ...
#else
#error "No way to define ev_uint64_t"
#endif
#ifdef EVENT__HAVE_UINT32_T
#define ev_uint32_t uint32_t
#define ev_int32_t int32_t
#elif defined(_WIN32)
#define ev_uint32_t unsigned int
#define ev_int32_t signed int
#elif EVENT__SIZEOF_LONG == 4
#define ev_uint32_t unsigned long
#define ev_int32_t signed long
#elif EVENT__SIZEOF_INT == 4
#define ev_uint32_t unsigned int
#define ev_int32_t signed int
#elif defined(EVENT_IN_DOXYGEN_)
#define ev_uint32_t ...
#define ev_int32_t ...
#else
#error "No way to define ev_uint32_t"
#endif
#ifdef EVENT__HAVE_UINT16_T
#define ev_uint16_t uint16_t
#define ev_int16_t int16_t
#elif defined(_WIN32)
#define ev_uint16_t unsigned short
#define ev_int16_t signed short
#elif EVENT__SIZEOF_INT == 2
#define ev_uint16_t unsigned int
#define ev_int16_t signed int
#elif EVENT__SIZEOF_SHORT == 2
#define ev_uint16_t unsigned short
#define ev_int16_t signed short
#elif defined(EVENT_IN_DOXYGEN_)
#define ev_uint16_t ...
#define ev_int16_t ...
#else
#error "No way to define ev_uint16_t"
#endif
#ifdef EVENT__HAVE_UINT8_T
#define ev_uint8_t uint8_t
#define ev_int8_t int8_t
#elif defined(EVENT_IN_DOXYGEN_)
#define ev_uint8_t ...
#define ev_int8_t ...
#else
#define ev_uint8_t unsigned char
#define ev_int8_t signed char
#endif
#ifdef EVENT__HAVE_UINTPTR_T
#define ev_uintptr_t uintptr_t
#define ev_intptr_t intptr_t
#elif EVENT__SIZEOF_VOID_P <= 4
#define ev_uintptr_t ev_uint32_t
#define ev_intptr_t ev_int32_t
#elif EVENT__SIZEOF_VOID_P <= 8
#define ev_uintptr_t ev_uint64_t
#define ev_intptr_t ev_int64_t
#elif defined(EVENT_IN_DOXYGEN_)
#define ev_uintptr_t ...
#define ev_intptr_t ...
#else
#error "No way to define ev_uintptr_t"
#endif
#ifdef EVENT__ssize_t
#define ev_ssize_t EVENT__ssize_t
#else
#define ev_ssize_t ssize_t
#endif
/* Note that we define ev_off_t based on the compile-time size of off_t that
* we used to build Libevent, and not based on the current size of off_t.
* (For example, we don't define ev_off_t to off_t.). We do this because
* some systems let you build your software with different off_t sizes
* at runtime, and so putting in any dependency on off_t would risk API
* mismatch.
*/
#ifdef _WIN32
#define ev_off_t ev_int64_t
#elif EVENT__SIZEOF_OFF_T == 8
#define ev_off_t ev_int64_t
#elif EVENT__SIZEOF_OFF_T == 4
#define ev_off_t ev_int32_t
#elif defined(EVENT_IN_DOXYGEN_)
#define ev_off_t ...
#else
#define ev_off_t off_t
#endif
/**@}*/
/* Limits for integer types.
We're making two assumptions here:
- The compiler does constant folding properly.
- The platform does signed arithmetic in two's complement.
*/
/**
@name Limits for integer types
These macros hold the largest or smallest values possible for the
ev_[u]int*_t types.
@{
*/
#ifndef EVENT__HAVE_STDINT_H
#define EV_UINT64_MAX ((((ev_uint64_t)0xffffffffUL) << 32) | 0xffffffffUL)
#define EV_INT64_MAX ((((ev_int64_t) 0x7fffffffL) << 32) | 0xffffffffL)
#define EV_INT64_MIN ((-EV_INT64_MAX) - 1)
#define EV_UINT32_MAX ((ev_uint32_t)0xffffffffUL)
#define EV_INT32_MAX ((ev_int32_t) 0x7fffffffL)
#define EV_INT32_MIN ((-EV_INT32_MAX) - 1)
#define EV_UINT16_MAX ((ev_uint16_t)0xffffUL)
#define EV_INT16_MAX ((ev_int16_t) 0x7fffL)
#define EV_INT16_MIN ((-EV_INT16_MAX) - 1)
#define EV_UINT8_MAX 255
#define EV_INT8_MAX 127
#define EV_INT8_MIN ((-EV_INT8_MAX) - 1)
#else
#define EV_UINT64_MAX UINT64_MAX
#define EV_INT64_MAX INT64_MAX
#define EV_INT64_MIN INT64_MIN
#define EV_UINT32_MAX UINT32_MAX
#define EV_INT32_MAX INT32_MAX
#define EV_INT32_MIN INT32_MIN
#define EV_UINT16_MAX UINT16_MAX
#define EV_INT16_MIN INT16_MIN
#define EV_INT16_MAX INT16_MAX
#define EV_UINT8_MAX UINT8_MAX
#define EV_INT8_MAX INT8_MAX
#define EV_INT8_MIN INT8_MIN
/** @} */
#endif
/**
@name Limits for SIZE_T and SSIZE_T
@{
*/
#if EVENT__SIZEOF_SIZE_T == 8
#define EV_SIZE_MAX EV_UINT64_MAX
#define EV_SSIZE_MAX EV_INT64_MAX
#elif EVENT__SIZEOF_SIZE_T == 4
#define EV_SIZE_MAX EV_UINT32_MAX
#define EV_SSIZE_MAX EV_INT32_MAX
#elif defined(EVENT_IN_DOXYGEN_)
#define EV_SIZE_MAX ...
#define EV_SSIZE_MAX ...
#else
#error "No way to define SIZE_MAX"
#endif
#define EV_SSIZE_MIN ((-EV_SSIZE_MAX) - 1)
/**@}*/
#ifdef _WIN32
#define ev_socklen_t int
#elif defined(EVENT__socklen_t)
#define ev_socklen_t EVENT__socklen_t
#else
#define ev_socklen_t socklen_t
#endif
#ifdef EVENT__HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY
#if !defined(EVENT__HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY) \
&& !defined(ss_family)
#define ss_family __ss_family
#endif
#endif
/**
* A type wide enough to hold the output of "socket()" or "accept()". On
* Windows, this is an intptr_t; elsewhere, it is an int. */
#ifdef _WIN32
#define evutil_socket_t intptr_t
#else
#define evutil_socket_t int
#endif
/**
* Structure to hold information about a monotonic timer
*
* Use this with evutil_configure_monotonic_time() and
* evutil_gettime_monotonic().
*
* This is an opaque structure; you can allocate one using
* evutil_monotonic_timer_new().
*
* @see evutil_monotonic_timer_new(), evutil_monotonic_timer_free(),
* evutil_configure_monotonic_time(), evutil_gettime_monotonic()
*/
struct evutil_monotonic_timer
#ifdef EVENT_IN_DOXYGEN_
{/*Empty body so that doxygen will generate documentation here.*/}
#endif
;
#define EV_MONOT_PRECISE 1
#define EV_MONOT_FALLBACK 2
/** Format a date string using RFC 1123 format (used in HTTP).
* If `tm` is NULL, current system's time will be used.
* The number of characters written will be returned.
* One should check if the return value is smaller than `datelen` to check if
* the result is truncated or not.
*/
EVENT2_EXPORT_SYMBOL int
evutil_date_rfc1123(char *date, const size_t datelen, const struct tm *tm);
/** Allocate a new struct evutil_monotonic_timer for use with the
* evutil_configure_monotonic_time() and evutil_gettime_monotonic()
* functions. You must configure the timer with
* evutil_configure_monotonic_time() before using it.
*/
EVENT2_EXPORT_SYMBOL
struct evutil_monotonic_timer * evutil_monotonic_timer_new(void);
/** Free a struct evutil_monotonic_timer that was allocated using
* evutil_monotonic_timer_new().
*/
EVENT2_EXPORT_SYMBOL
void evutil_monotonic_timer_free(struct evutil_monotonic_timer *timer);
/** Set up a struct evutil_monotonic_timer; flags can include
* EV_MONOT_PRECISE and EV_MONOT_FALLBACK.
*/
EVENT2_EXPORT_SYMBOL
int evutil_configure_monotonic_time(struct evutil_monotonic_timer *timer,
int flags);
/** Query the current monotonic time from a struct evutil_monotonic_timer
* previously configured with evutil_configure_monotonic_time(). Monotonic
* time is guaranteed never to run in reverse, but is not necessarily epoch-
* based, or relative to any other definite point. Use it to make reliable
* measurements of elapsed time between events even when the system time
* may be changed.
*
* It is not safe to use this funtion on the same timer from multiple
* threads.
*/
EVENT2_EXPORT_SYMBOL
int evutil_gettime_monotonic(struct evutil_monotonic_timer *timer,
struct timeval *tp);
/** Create two new sockets that are connected to each other.
On Unix, this simply calls socketpair(). On Windows, it uses the
loopback network interface on 127.0.0.1, and only
AF_INET,SOCK_STREAM are supported.
(This may fail on some Windows hosts where firewall software has cleverly
decided to keep 127.0.0.1 from talking to itself.)
Parameters and return values are as for socketpair()
*/
EVENT2_EXPORT_SYMBOL
int evutil_socketpair(int d, int type, int protocol, evutil_socket_t sv[2]);
/** Do platform-specific operations as needed to make a socket nonblocking.
@param sock The socket to make nonblocking
@return 0 on success, -1 on failure
*/
EVENT2_EXPORT_SYMBOL
int evutil_make_socket_nonblocking(evutil_socket_t sock);
/** Do platform-specific operations to make a listener socket reusable.
Specifically, we want to make sure that another program will be able
to bind this address right after we've closed the listener.
This differs from Windows's interpretation of "reusable", which
allows multiple listeners to bind the same address at the same time.
@param sock The socket to make reusable
@return 0 on success, -1 on failure
*/
EVENT2_EXPORT_SYMBOL
int evutil_make_listen_socket_reuseable(evutil_socket_t sock);
/** Do platform-specific operations to make a listener port reusable.
Specifically, we want to make sure that multiple programs which also
set the same socket option will be able to bind, listen at the same time.
This is a feature available only to Linux 3.9+
@param sock The socket to make reusable
@return 0 on success, -1 on failure
*/
EVENT2_EXPORT_SYMBOL
int evutil_make_listen_socket_reuseable_port(evutil_socket_t sock);
/** Set ipv6 only bind socket option to make listener work only in ipv6 sockets.
According to RFC3493 and most Linux distributions, default value for the
sockets is to work in IPv4-mapped mode. In IPv4-mapped mode, it is not possible
to bind same port from different IPv4 and IPv6 handlers.
@param sock The socket to make in ipv6only working mode
@return 0 on success, -1 on failure
*/
EVENT2_EXPORT_SYMBOL
int evutil_make_listen_socket_ipv6only(evutil_socket_t sock);
/** Do platform-specific operations as needed to close a socket upon a
successful execution of one of the exec*() functions.
@param sock The socket to be closed
@return 0 on success, -1 on failure
*/
EVENT2_EXPORT_SYMBOL
int evutil_make_socket_closeonexec(evutil_socket_t sock);
/** Do the platform-specific call needed to close a socket returned from
socket() or accept().
@param sock The socket to be closed
@return 0 on success (whether the operation is supported or not),
-1 on failure
*/
EVENT2_EXPORT_SYMBOL
int evutil_closesocket(evutil_socket_t sock);
#define EVUTIL_CLOSESOCKET(s) evutil_closesocket(s)
/** Do platform-specific operations, if possible, to make a tcp listener
* socket defer accept()s until there is data to read.
*
* Not all platforms support this. You don't want to do this for every
* listener socket: only the ones that implement a protocol where the
* client transmits before the server needs to respond.
*
* @param sock The listening socket to to make deferred
* @return 0 on success (whether the operation is supported or not),
* -1 on failure
*/
EVENT2_EXPORT_SYMBOL
int evutil_make_tcp_listen_socket_deferred(evutil_socket_t sock);
#ifdef _WIN32
/** Return the most recent socket error. Not idempotent on all platforms. */
#define EVUTIL_SOCKET_ERROR() WSAGetLastError()
/** Replace the most recent socket error with errcode */
#define EVUTIL_SET_SOCKET_ERROR(errcode) \
do { WSASetLastError(errcode); } while (0)
/** Return the most recent socket error to occur on sock. */
EVENT2_EXPORT_SYMBOL
int evutil_socket_geterror(evutil_socket_t sock);
/** Convert a socket error to a string. */
EVENT2_EXPORT_SYMBOL
const char *evutil_socket_error_to_string(int errcode);
#define EVUTIL_INVALID_SOCKET INVALID_SOCKET
#elif defined(EVENT_IN_DOXYGEN_)
/**
@name Socket error functions
These functions are needed for making programs compatible between
Windows and Unix-like platforms.
You see, Winsock handles socket errors differently from the rest of
the world. Elsewhere, a socket error is like any other error and is
stored in errno. But winsock functions require you to retrieve the
error with a special function, and don't let you use strerror for
the error codes. And handling EWOULDBLOCK is ... different.
@{
*/
/** Return the most recent socket error. Not idempotent on all platforms. */
#define EVUTIL_SOCKET_ERROR() ...
/** Replace the most recent socket error with errcode */
#define EVUTIL_SET_SOCKET_ERROR(errcode) ...
/** Return the most recent socket error to occur on sock. */
#define evutil_socket_geterror(sock) ...
/** Convert a socket error to a string. */
#define evutil_socket_error_to_string(errcode) ...
#define EVUTIL_INVALID_SOCKET -1
/**@}*/
#else /** !EVENT_IN_DOXYGEN_ && !_WIN32 */
#define EVUTIL_SOCKET_ERROR() (errno)
#define EVUTIL_SET_SOCKET_ERROR(errcode) \
do { errno = (errcode); } while (0)
#define evutil_socket_geterror(sock) (errno)
#define evutil_socket_error_to_string(errcode) (strerror(errcode))
#define EVUTIL_INVALID_SOCKET -1
#endif /** !_WIN32 */
/**
* @name Manipulation macros for struct timeval.
*
* We define replacements
* for timeradd, timersub, timerclear, timercmp, and timerisset.
*
* @{
*/
#ifdef EVENT__HAVE_TIMERADD
#define evutil_timeradd(tvp, uvp, vvp) timeradd((tvp), (uvp), (vvp))
#define evutil_timersub(tvp, uvp, vvp) timersub((tvp), (uvp), (vvp))
#else
#define evutil_timeradd(tvp, uvp, vvp) \
do { \
(vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \
(vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \
if ((vvp)->tv_usec >= 1000000) { \
(vvp)->tv_sec++; \
(vvp)->tv_usec -= 1000000; \
} \
} while (0)
#define evutil_timersub(tvp, uvp, vvp) \
do { \
(vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
(vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
if ((vvp)->tv_usec < 0) { \
(vvp)->tv_sec--; \
(vvp)->tv_usec += 1000000; \
} \
} while (0)
#endif /* !EVENT__HAVE_TIMERADD */
#ifdef EVENT__HAVE_TIMERCLEAR
#define evutil_timerclear(tvp) timerclear(tvp)
#else
#define evutil_timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0
#endif
/**@}*/
/** Return true iff the tvp is related to uvp according to the relational
* operator cmp. Recognized values for cmp are ==, <=, <, >=, and >. */
#define evutil_timercmp(tvp, uvp, cmp) \
(((tvp)->tv_sec == (uvp)->tv_sec) ? \
((tvp)->tv_usec cmp (uvp)->tv_usec) : \
((tvp)->tv_sec cmp (uvp)->tv_sec))
#ifdef EVENT__HAVE_TIMERISSET
#define evutil_timerisset(tvp) timerisset(tvp)
#else
#define evutil_timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
#endif
/** Replacement for offsetof on platforms that don't define it. */
#ifdef offsetof
#define evutil_offsetof(type, field) offsetof(type, field)
#else
#define evutil_offsetof(type, field) ((off_t)(&((type *)0)->field))
#endif
/* big-int related functions */
/** Parse a 64-bit value from a string. Arguments are as for strtol. */
EVENT2_EXPORT_SYMBOL
ev_int64_t evutil_strtoll(const char *s, char **endptr, int base);
/** Replacement for gettimeofday on platforms that lack it. */
#ifdef EVENT__HAVE_GETTIMEOFDAY
#define evutil_gettimeofday(tv, tz) gettimeofday((tv), (tz))
#else
struct timezone;
EVENT2_EXPORT_SYMBOL
int evutil_gettimeofday(struct timeval *tv, struct timezone *tz);
#endif
/** Replacement for snprintf to get consistent behavior on platforms for
which the return value of snprintf does not conform to C99.
*/
EVENT2_EXPORT_SYMBOL
int evutil_snprintf(char *buf, size_t buflen, const char *format, ...)
#ifdef __GNUC__
__attribute__((format(printf, 3, 4)))
#endif
;
/** Replacement for vsnprintf to get consistent behavior on platforms for
which the return value of snprintf does not conform to C99.
*/
EVENT2_EXPORT_SYMBOL
int evutil_vsnprintf(char *buf, size_t buflen, const char *format, va_list ap)
#ifdef __GNUC__
__attribute__((format(printf, 3, 0)))
#endif
;
/** Replacement for inet_ntop for platforms which lack it. */
EVENT2_EXPORT_SYMBOL
const char *evutil_inet_ntop(int af, const void *src, char *dst, size_t len);
/** Variation of inet_pton that also parses IPv6 scopes. Public for
unit tests. No reason to call this directly.
*/
EVENT2_EXPORT_SYMBOL
int evutil_inet_pton_scope(int af, const char *src, void *dst,
unsigned *indexp);
/** Replacement for inet_pton for platforms which lack it. */
EVENT2_EXPORT_SYMBOL
int evutil_inet_pton(int af, const char *src, void *dst);
struct sockaddr;
/** Parse an IPv4 or IPv6 address, with optional port, from a string.
Recognized formats are:
- [IPv6Address]:port
- [IPv6Address]
- IPv6Address
- IPv4Address:port
- IPv4Address
If no port is specified, the port in the output is set to 0.
@param str The string to parse.
@param out A struct sockaddr to hold the result. This should probably be
a struct sockaddr_storage.
@param outlen A pointer to the number of bytes that that 'out' can safely
hold. Set to the number of bytes used in 'out' on success.
@return -1 if the address is not well-formed, if the port is out of range,
or if out is not large enough to hold the result. Otherwise returns
0 on success.
*/
EVENT2_EXPORT_SYMBOL
int evutil_parse_sockaddr_port(const char *str, struct sockaddr *out, int *outlen);
/** Compare two sockaddrs; return 0 if they are equal, or less than 0 if sa1
* preceeds sa2, or greater than 0 if sa1 follows sa2. If include_port is
* true, consider the port as well as the address. Only implemented for
* AF_INET and AF_INET6 addresses. The ordering is not guaranteed to remain
* the same between Libevent versions. */
EVENT2_EXPORT_SYMBOL
int evutil_sockaddr_cmp(const struct sockaddr *sa1, const struct sockaddr *sa2,
int include_port);
/** As strcasecmp, but always compares the characters in locale-independent
ASCII. That's useful if you're handling data in ASCII-based protocols.
*/
EVENT2_EXPORT_SYMBOL
int evutil_ascii_strcasecmp(const char *str1, const char *str2);
/** As strncasecmp, but always compares the characters in locale-independent
ASCII. That's useful if you're handling data in ASCII-based protocols.
*/
EVENT2_EXPORT_SYMBOL
int evutil_ascii_strncasecmp(const char *str1, const char *str2, size_t n);
/* Here we define evutil_addrinfo to the native addrinfo type, or redefine it
* if this system has no getaddrinfo(). */
#ifdef EVENT__HAVE_STRUCT_ADDRINFO
#define evutil_addrinfo addrinfo
#else
/** A definition of struct addrinfo for systems that lack it.
(This is just an alias for struct addrinfo if the system defines
struct addrinfo.)
*/
struct evutil_addrinfo {
int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
int ai_family; /* PF_xxx */
int ai_socktype; /* SOCK_xxx */
int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
size_t ai_addrlen; /* length of ai_addr */
char *ai_canonname; /* canonical name for nodename */
struct sockaddr *ai_addr; /* binary address */
struct evutil_addrinfo *ai_next; /* next structure in linked list */
};
#endif
/** @name evutil_getaddrinfo() error codes
These values are possible error codes for evutil_getaddrinfo() and
related functions.
@{
*/
#if defined(EAI_ADDRFAMILY) && defined(EVENT__HAVE_GETADDRINFO)
#define EVUTIL_EAI_ADDRFAMILY EAI_ADDRFAMILY
#else
#define EVUTIL_EAI_ADDRFAMILY -901
#endif
#if defined(EAI_AGAIN) && defined(EVENT__HAVE_GETADDRINFO)
#define EVUTIL_EAI_AGAIN EAI_AGAIN
#else
#define EVUTIL_EAI_AGAIN -902
#endif
#if defined(EAI_BADFLAGS) && defined(EVENT__HAVE_GETADDRINFO)
#define EVUTIL_EAI_BADFLAGS EAI_BADFLAGS
#else
#define EVUTIL_EAI_BADFLAGS -903
#endif
#if defined(EAI_FAIL) && defined(EVENT__HAVE_GETADDRINFO)
#define EVUTIL_EAI_FAIL EAI_FAIL
#else
#define EVUTIL_EAI_FAIL -904
#endif
#if defined(EAI_FAMILY) && defined(EVENT__HAVE_GETADDRINFO)
#define EVUTIL_EAI_FAMILY EAI_FAMILY
#else
#define EVUTIL_EAI_FAMILY -905
#endif
#if defined(EAI_MEMORY) && defined(EVENT__HAVE_GETADDRINFO)
#define EVUTIL_EAI_MEMORY EAI_MEMORY
#else
#define EVUTIL_EAI_MEMORY -906
#endif
/* This test is a bit complicated, since some MS SDKs decide to
* remove NODATA or redefine it to be the same as NONAME, in a
* fun interpretation of RFC 2553 and RFC 3493. */
#if defined(EAI_NODATA) && defined(EVENT__HAVE_GETADDRINFO) && (!defined(EAI_NONAME) || EAI_NODATA != EAI_NONAME)
#define EVUTIL_EAI_NODATA EAI_NODATA
#else
#define EVUTIL_EAI_NODATA -907
#endif
#if defined(EAI_NONAME) && defined(EVENT__HAVE_GETADDRINFO)
#define EVUTIL_EAI_NONAME EAI_NONAME
#else
#define EVUTIL_EAI_NONAME -908
#endif
#if defined(EAI_SERVICE) && defined(EVENT__HAVE_GETADDRINFO)
#define EVUTIL_EAI_SERVICE EAI_SERVICE
#else
#define EVUTIL_EAI_SERVICE -909
#endif
#if defined(EAI_SOCKTYPE) && defined(EVENT__HAVE_GETADDRINFO)
#define EVUTIL_EAI_SOCKTYPE EAI_SOCKTYPE
#else
#define EVUTIL_EAI_SOCKTYPE -910
#endif
#if defined(EAI_SYSTEM) && defined(EVENT__HAVE_GETADDRINFO)
#define EVUTIL_EAI_SYSTEM EAI_SYSTEM
#else
#define EVUTIL_EAI_SYSTEM -911
#endif
#define EVUTIL_EAI_CANCEL -90001
#if defined(AI_PASSIVE) && defined(EVENT__HAVE_GETADDRINFO)
#define EVUTIL_AI_PASSIVE AI_PASSIVE
#else
#define EVUTIL_AI_PASSIVE 0x1000
#endif
#if defined(AI_CANONNAME) && defined(EVENT__HAVE_GETADDRINFO)
#define EVUTIL_AI_CANONNAME AI_CANONNAME
#else
#define EVUTIL_AI_CANONNAME 0x2000
#endif
#if defined(AI_NUMERICHOST) && defined(EVENT__HAVE_GETADDRINFO)
#define EVUTIL_AI_NUMERICHOST AI_NUMERICHOST
#else
#define EVUTIL_AI_NUMERICHOST 0x4000
#endif
#if defined(AI_NUMERICSERV) && defined(EVENT__HAVE_GETADDRINFO)
#define EVUTIL_AI_NUMERICSERV AI_NUMERICSERV
#else
#define EVUTIL_AI_NUMERICSERV 0x8000
#endif
#if defined(AI_V4MAPPED) && defined(EVENT__HAVE_GETADDRINFO)
#define EVUTIL_AI_V4MAPPED AI_V4MAPPED
#else
#define EVUTIL_AI_V4MAPPED 0x10000
#endif
#if defined(AI_ALL) && defined(EVENT__HAVE_GETADDRINFO)
#define EVUTIL_AI_ALL AI_ALL
#else
#define EVUTIL_AI_ALL 0x20000
#endif
#if defined(AI_ADDRCONFIG) && defined(EVENT__HAVE_GETADDRINFO)
#define EVUTIL_AI_ADDRCONFIG AI_ADDRCONFIG
#else
#define EVUTIL_AI_ADDRCONFIG 0x40000
#endif
/**@}*/
struct evutil_addrinfo;
/**
* This function clones getaddrinfo for systems that don't have it. For full
* details, see RFC 3493, section 6.1.
*
* Limitations:
* - When the system has no getaddrinfo, we fall back to gethostbyname_r or
* gethostbyname, with their attendant issues.
* - The AI_V4MAPPED and AI_ALL flags are not currently implemented.
*
* For a nonblocking variant, see evdns_getaddrinfo.
*/
EVENT2_EXPORT_SYMBOL
int evutil_getaddrinfo(const char *nodename, const char *servname,
const struct evutil_addrinfo *hints_in, struct evutil_addrinfo **res);
/** Release storage allocated by evutil_getaddrinfo or evdns_getaddrinfo. */
EVENT2_EXPORT_SYMBOL
void evutil_freeaddrinfo(struct evutil_addrinfo *ai);
EVENT2_EXPORT_SYMBOL
const char *evutil_gai_strerror(int err);
/** Generate n bytes of secure pseudorandom data, and store them in buf.
*
* Current versions of Libevent use an ARC4-based random number generator,
* seeded using the platform's entropy source (/dev/urandom on Unix-like
* systems; CryptGenRandom on Windows). This is not actually as secure as it
* should be: ARC4 is a pretty lousy cipher, and the current implementation
* provides only rudimentary prediction- and backtracking-resistance. Don't
* use this for serious cryptographic applications.
*/
EVENT2_EXPORT_SYMBOL
void evutil_secure_rng_get_bytes(void *buf, size_t n);
/**
* Seed the secure random number generator if needed, and return 0 on
* success or -1 on failure.
*
* It is okay to call this function more than once; it will still return
* 0 if the RNG has been successfully seeded and -1 if it can't be
* seeded.
*
* Ordinarily you don't need to call this function from your own code;
* Libevent will seed the RNG itself the first time it needs good random
* numbers. You only need to call it if (a) you want to double-check
* that one of the seeding methods did succeed, or (b) you plan to drop
* the capability to seed (by chrooting, or dropping capabilities, or
* whatever), and you want to make sure that seeding happens before your
* program loses the ability to do it.
*/
EVENT2_EXPORT_SYMBOL
int evutil_secure_rng_init(void);
/**
* Set a filename to use in place of /dev/urandom for seeding the secure
* PRNG. Return 0 on success, -1 on failure.
*
* Call this function BEFORE calling any other initialization or RNG
* functions.
*
* (This string will _NOT_ be copied internally. Do not free it while any
* user of the secure RNG might be running. Don't pass anything other than a
* real /dev/...random device file here, or you might lose security.)
*
* This API is unstable, and might change in a future libevent version.
*/
EVENT2_EXPORT_SYMBOL
int evutil_secure_rng_set_urandom_device_file(char *fname);
#if !defined(EVENT__HAVE_ARC4RANDOM) || defined(EVENT__HAVE_ARC4RANDOM_ADDRANDOM)
/** Seed the random number generator with extra random bytes.
You should almost never need to call this function; it should be
sufficient to invoke evutil_secure_rng_init(), or let Libevent take
care of calling evutil_secure_rng_init() on its own.
If you call this function as a _replacement_ for the regular
entropy sources, then you need to be sure that your input
contains a fairly large amount of strong entropy. Doing so is
notoriously hard: most people who try get it wrong. Watch out!
@param dat a buffer full of a strong source of random numbers
@param datlen the number of bytes to read from datlen
*/
EVENT2_EXPORT_SYMBOL
void evutil_secure_rng_add_bytes(const char *dat, size_t datlen);
#endif
#ifdef __cplusplus
}
#endif
#endif /* EVENT1_EVUTIL_H_INCLUDED_ */

View File

@@ -0,0 +1,67 @@
/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
* 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_VISIBILITY_H_INCLUDED_
#define EVENT2_VISIBILITY_H_INCLUDED_
#include <event2/event-config.h>
#if defined(event_shared_EXPORTS) || \
defined(event_extra_shared_EXPORTS) || \
defined(event_core_shared_EXPORTS) || \
defined(event_pthreads_shared_EXPORTS) || \
defined(event_openssl_shared_EXPORTS)
# if defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
# define EVENT2_EXPORT_SYMBOL __global
# elif defined __GNUC__
# define EVENT2_EXPORT_SYMBOL __attribute__ ((visibility("default")))
# elif defined(_MSC_VER)
# define EVENT2_EXPORT_SYMBOL __declspec(dllexport)
# else
# define EVENT2_EXPORT_SYMBOL /* unknown compiler */
# endif
#else /* event_*_EXPORTS */
# define EVENT2_EXPORT_SYMBOL
#endif /* event_*_EXPORTS */
/** We need to dllimport event_debug_logging_mask_ into event_extra */
#if defined(_MSC_VER)
# if defined(event_core_shared_EXPORTS) /** from core export */
# define EVENT2_CORE_EXPORT_SYMBOL __declspec(dllexport)
# elif defined(event_extra_shared_EXPORTS) || /** from extra import */ \
defined(EVENT_VISIBILITY_WANT_DLLIMPORT)
# define EVENT2_CORE_EXPORT_SYMBOL __declspec(dllimport)
# endif
#endif /* _MSC_VER */
#if !defined(EVENT2_CORE_EXPORT_SYMBOL)
# define EVENT2_CORE_EXPORT_SYMBOL EVENT2_EXPORT_SYMBOL
#endif
#endif /* EVENT2_VISIBILITY_H_INCLUDED_ */

45
thirdparty/include/libevent/evhttp.h vendored Normal file
View File

@@ -0,0 +1,45 @@
/*
* Copyright 2000-2007 Niels Provos <provos@citi.umich.edu>
* Copyright 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_EVHTTP_H_INCLUDED_
#define EVENT1_EVHTTP_H_INCLUDED_
/** @file evhttp.h
An http implementation subsystem for Libevent.
The <evhttp.h> header is deprecated in Libevent 2.0 and later; please
use <event2/http.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/http.h>
#include <event2/http_struct.h>
#include <event2/http_compat.h>
#endif /* EVENT1_EVHTTP_H_INCLUDED_ */

45
thirdparty/include/libevent/evrpc.h vendored Normal file
View 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_EVRPC_H_INCLUDED_
#define EVENT1_EVRPC_H_INCLUDED_
/** @file evrpc.h
An RPC system for Libevent.
The <evrpc.h> header is deprecated in Libevent 2.0 and later; please
use <event2/rpc.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/rpc.h>
#include <event2/rpc_struct.h>
#include <event2/rpc_compat.h>
#endif /* EVENT1_EVRPC_H_INCLUDED_ */

39
thirdparty/include/libevent/evutil.h vendored Normal file
View File

@@ -0,0 +1,39 @@
/*
* 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_EVUTIL_H_INCLUDED_
#define EVENT1_EVUTIL_H_INCLUDED_
/** @file evutil.h
Utility and compatibility functions for Libevent.
The <evutil.h> header is deprecated in Libevent 2.0 and later; please
use <event2/util.h> instead.
*/
#include <event2/util.h>
#endif /* EVENT1_EVUTIL_H_INCLUDED_ */

55
thirdparty/json-c/.clang-format vendored Normal file
View File

@@ -0,0 +1,55 @@
BasedOnStyle: LLVM
# If true, clang-format will attempt to re-flow comments
ReflowComments: false
# The column limit.
ColumnLimit: 100
# Indent width for line continuations.
ContinuationIndentWidth: 4
# The number of columns to use for indentation.
IndentWidth: 8
# The number of columns used for tab stops.
TabWidth: 8
UseTab: ForIndentation
# Options for aligning backslashes in escaped newlines.
AlignEscapedNewlines: Left
# Short Block Style
AllowShortBlocksOnASingleLine: true
# If true, short case labels will be contracted to a single line.
AllowShortCaseLabelsOnASingleLine: true
# Dependent on the value, int f() { return 0; } can be put on a single line.
AllowShortFunctionsOnASingleLine: Empty
# The brace breaking style to use.
BreakBeforeBraces: Custom
# Control of individual brace wrapping cases.
BraceWrapping:
# Wrap brackets inside of a case
AfterCaseLabel: true
# Wrap class definition.
AfterClass: true
# Wrap control statements
AfterControlStatement: true
# Wrap enum definitions.
AfterEnum: true
# Wrap function definitions.
AfterFunction: true
# Wrap namespace definitions.
AfterNamespace: true
# Wrap struct definitions.
AfterStruct: true
# Wrap union definitions.
AfterUnion: true
# Wrap extern blocks.
AfterExternBlock: false
# Wrap before catch.
BeforeCatch: true
# Wrap before else.
BeforeElse: true
# Indent the wrapped braces themselves.
IndentBraces: false
# If false, empty function body can be put on a single line.
SplitEmptyFunction: false
# If false, empty record (e.g. class, struct or union) body can be put on a single line.
SplitEmptyRecord: false
# If false, empty namespace body can be put on a single line.
SplitEmptyNamespace: false

15
thirdparty/json-c/.editorconfig vendored Normal file
View File

@@ -0,0 +1,15 @@
# EditorConfig
# https://EditorConfig.org
# top-most EditorConfig file
root = true
# LF end-of-line, insert an empty new line and UTF-8
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
# Tab indentation
[makefile,Makefile]
indent_style = tab

View File

@@ -0,0 +1,23 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
Note: for general questions and comments, please use the forums at:
https://groups.google.com/g/json-c
**Describe the bug**
A clear and concise description of what the bug is, and any information about where you're running into the bug that you feel might be relevant.
**Steps To Reproduce**
List the steps to reproduce the behavior.
If possible, please attach a sample json file and/or a minimal code example.
**Version and Platform**
- json-c version: [e.g. json-c-0.14, or a specific commit hash]
- OS: [e.g. Ubuntu 20.04, Debian Buster, NetBSD 9, etc...]
- Custom cmake/build flags, if any

95
thirdparty/json-c/.gitignore vendored Normal file
View File

@@ -0,0 +1,95 @@
# Temp files
*~
*.swp
*.bak
*.backup
\#*
.\#*
*\#
*.sav
*.save
*.autosav
*.autosave
# Tests
/tests/Makefile
/tests/test1
/tests/test1Formatted
/tests/test2
/tests/test2Formatted
/tests/test4
/tests/testReplaceExisting
/tests/testSubDir
/tests/test_cast
/tests/test_charcase
/tests/test_compare
/tests/test_deep_copy
/tests/test_double_serializer
/tests/test_float
/tests/test_int_add
/tests/test_int_get
/tests/test_json_pointer
/tests/test_locale
/tests/test_null
/tests/test_parse
/tests/test_parse_int64
/tests/test_printbuf
/tests/test_set_serializer
/tests/test_set_value
/tests/test_util_file
/tests/test_visit
/tests/*.vg.out
/tests/*.log
/tests/*.trs
# Generated folders
/build
/Debug
/Release
/*/Debug
/*/Release
# Archives
*.zip
*.tar.*
*.tgz
*.gz
*.bz2
*.xz
*.lz
*.lzma
*.7z
*.dll
*.deb
*.rpm
*.apk
*.exe
*.msi
*.dmg
*.ipa
# It's not good practice to build directly in the source tree
# but ignore cmake auto-generated files anyway:
/json_config.h
/json.h
/config.h
/json-c.pc
/Makefile
/CMakeCache.txt
/CMakeFiles
/CMakeDoxyfile.in
/*.cmake
/DartConfiguration.tcl
/tests/CMakeFiles/
/tests/*.cmake
/Testing/
# ...and build artifacts.
/doc/html
/libjson-c.a
/libjson-c.so
/libjson-c.so.*
# Benchmarking input and output
/bench/data
/bench/work

147
thirdparty/json-c/.travis.yml vendored Normal file
View File

@@ -0,0 +1,147 @@
language: cpp
matrix:
include:
# ubuntu xenial 16.04
# gcc 5 is the default on xenial
- os: linux
dist: xenial
compiler: gcc
addons:
apt:
packages:
- valgrind
- cppcheck
- doxygen
- cmake
env: CHECK="true"
# ubuntu bionic 18.04
# gcc 7 is the default on bionic
- os: linux
dist: bionic
compiler: gcc
addons:
apt:
packages:
- valgrind
- cppcheck
- doxygen
- cmake
env: CHECK="true"
# ubuntu focal fossa 20.04
# gcc 9 is the default on bionic
- os: linux
dist: focal
compiler: gcc
addons:
apt:
packages:
- valgrind
- cppcheck
- doxygen
- cmake
env: CHECK="true"
# clang
# xenial
- os: linux
dist: xenial
compiler: clang
addons:
apt:
sources:
- llvm-toolchain-xenial-6.0
packages:
- clang-6.0
- cmake
env: MATRIX_EVAL="CC=clang-6.0 && CXX=clang++-6.0"
# clang-7 is the default on focal, xenial and bionic
- os: linux
dist: focal
compiler: clang
addons:
apt:
packages:
- valgrind
- cppcheck
- doxygen
- cmake
env: CHECK="true"
# osx
- os: osx
osx_image: xcode13.4
env: XCODE="true" CHECK="true"
# run coveralls
- os: linux
dist: xenial
compiler: gcc
addons:
apt:
packages:
- lcov
env: CHECK="true"
before_install:
- sudo gem install coveralls-lcov
- echo $CC
- echo $LANG
- echo $LC_ALL
- set -e
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then
eval "${MATRIX_EVAL}";
if [ -n "$MATRIX_EVAL" ] && [ "$TRAVIS_COMPILER" != "clang" ]; then
sudo apt-get install -y $CC;
fi;
fi
before_script:
- export CFLAGS="-fprofile-arcs -ftest-coverage"
- mkdir build && cd build && cmake ..
script:
- make
- make test
after_success:
- cd ..
- lcov -d build/ -b . -c -o build/all_coverage.info
- lcov -r build/all_coverage.info '/usr/*' '*CMakeFiles*' '*fuzz*' '*test*' -o build/coverage.info
- coveralls-lcov --verbose build/coverage.info
# allow_failures:
# - os: osx
before_install:
- echo $CC
- echo $LANG
- echo $LC_ALL
- set -e
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then
eval "${MATRIX_EVAL}";
if [ -n "$MATRIX_EVAL" ] && [ "$TRAVIS_COMPILER" != "clang" ]; then
sudo apt-get install -y $CC;
fi;
fi
before_script:
# XXX osx on travis doesn't work w/ set -e, so turn it off :(
- set +e
- mkdir -p build || echo "Failed to mkdir build"
- cd build || echo "Failed to cd build"
- cmake .. || echo "Failed to run cmake"
script:
- make
# when using bionic, Travis seems to ignore the "addons" section, so installing the packages with apt-get...
- if [ -n "$CHECK" ]; then
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
brew install doxygen;
else
if [ "$TRAVIS_DIST" = "bionic" ]; then
sudo apt-get install -y valgrind cppcheck doxygen;
fi;
fi;
make distcheck;
if type cppcheck &> /dev/null ; then cppcheck --error-exitcode=1 --quiet *.h *.c tests/ ; fi;
fi

61
thirdparty/json-c/AUTHORS vendored Normal file
View File

@@ -0,0 +1,61 @@
Alan Coopersmith <alan.coopersmith@oracle.com>
Alexander Dahl <post@lespocky.de>
Alexandru Ardelean <ardeleanalex@gmail.com>
andy5995 <andy400-dev@yahoo.com>
Aram Poghosyan <Aram.Poghosyan@teamviewer.com>
Björn Esser <besser82@fedoraproject.org>
BonsaY <bonsay@posteo.de>
changyong guo <guo1487@163.com>
chenguoping <chenguopingdota@163.com>
Chris Lamb <lamby@debian.org>
Christopher Head <chead@chead.ca>
Chris Wolfe <chriswwolfe@gmail.com>
C. Watford (christopher.watford@gmail.com)
Darjan Krijan <darjan_krijan@gmx.de>
David McCann <mccannd@uk.ibm.com>
DeX77 <dex@dragonslave.de>
dota17 <chenguopingdota@163.com>
Eric Haszlakiewicz <erh+git@nimenees.com>
Eric Hawicz <erh+git@nimenees.com>
Even Rouault <even.rouault@spatialys.com>
Gianluigi Tiesi <sherpya@netfarm.it>
grdowns <grdowns@microsoft.com>
Hex052 <elijahiff@gmail.com>
hofnarr <hofnarr@hofnarr.fi>
ihsinme <61293369+ihsinme@users.noreply.github.com>
Ivan Romanov <drizt@land.ru>
Jaap Keuter <jaap.keuter@xs4all.nl>
Jakov Smolic <jakov.smolic@sartura.hr>
janczer <menshikov.ivn@gmail.com>
Jehan <jehan@girinstud.io>
Jehiah Czebotar <jehiah@gmail.com>
Jonathan Wiens <j.wiens@teles.com>
Jose Bollo <jose.bollo@iot.bzh>
José Bollo <jose.bollo@iot.bzh>
Juuso Alasuutari <juuso.alasuutari@gmail.com>
Keith Holman <keith.holman@windriver.com>
Kizuna-Meraki <z9@kizunameraki.de>
Leon Gross <leon.gross@rub.de>
Liang, Gao <liang.gao@intel.com>
Marc <34656315+MarcT512@users.noreply.github.com>
max <mpano91@gmail.com>
Micah Snyder <micasnyd@cisco.com>
Michael Clark <michael@metaparadigm.com>
myd7349 <myd7349@gmail.com>
Pascal Cuoq <cuoq@trust-in-soft.com>
Pawday <pawday@mail.ru>
Philosoph228 <philosoph228@gmail.com>
Pierce Lopez <pierce.lopez@gmail.com>
Po-Chuan Hsieh <sunpoet@sunpoet.net>
Ramiro Polla <ramiro.polla@gmail.com>
Rikard Falkeborn <rikard.falkeborn@gmail.com>
Robert Bielik <robert.bielik@dirac.com>
Robert <roby_p97@yahoo.com>
Rosen Penev <rosenp@gmail.com>
Rubasri Kalidas <rubasri.kalidas@intel.com>
Simon McVittie <smcv@collabora.com>
ssrlive <30760636+ssrlive@users.noreply.github.com>
Tobias Nießen <tniessen@users.noreply.github.com>
Tobias Stoeckmann <tobias@stoeckmann.org>
Tudor Brindus <me@tbrindus.ca>
Unmanned Player <36690541+unmanned-player@users.noreply.github.com>

49
thirdparty/json-c/Android.configure.mk vendored Normal file
View File

@@ -0,0 +1,49 @@
# This file is the top android makefile for all sub-modules.
#
# Suggested settings to build for Android:
#
# export PATH=$PATH:/opt/android-ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/
# export SYSROOT=/opt/android-ndk/platforms/android-9/arch-arm/usr/
# export LD=arm-linux-androideabi-ld
# export CC="arm-linux-androideabi-gcc --sysroot=/opt/android-ndk/platforms/android-9/arch-arm"
#
# Then run autogen.sh, configure and make.
#
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
json_c_TOP := $(LOCAL_PATH)
JSON_C_BUILT_SOURCES := Android.mk
JSON_C_BUILT_SOURCES := $(patsubst %, $(abspath $(json_c_TOP))/%, $(JSON_C_BUILT_SOURCES))
.PHONY: json-c-configure json-c-configure-real
json-c-configure-real:
echo $(JSON_C_BUILT_SOURCES)
cd $(json_c_TOP) ; \
$(abspath $(json_c_TOP))/autogen.sh && \
CC="$(CONFIGURE_CC)" \
CFLAGS="$(CONFIGURE_CFLAGS)" \
LD=$(TARGET_LD) \
LDFLAGS="$(CONFIGURE_LDFLAGS)" \
CPP=$(CONFIGURE_CPP) \
CPPFLAGS="$(CONFIGURE_CPPFLAGS)" \
PKG_CONFIG_LIBDIR=$(CONFIGURE_PKG_CONFIG_LIBDIR) \
PKG_CONFIG_TOP_BUILD_DIR=/ \
ac_cv_func_malloc_0_nonnull=yes \
ac_cv_func_realloc_0_nonnull=yes \
$(abspath $(json_c_TOP))/$(CONFIGURE) --host=$(CONFIGURE_HOST) \
--prefix=/system \
&& \
for file in $(JSON_C_BUILT_SOURCES); do \
rm -f $$file && \
make -C $$(dirname $$file) $$(basename $$file) ; \
done
json-c-configure: json-c-configure-real
PA_CONFIGURE_TARGETS += json-c-configure
-include $(json_c_TOP)/Android.mk

585
thirdparty/json-c/CMakeLists.txt vendored Normal file
View File

@@ -0,0 +1,585 @@
# Many projects still are stuck using CMake 2.8 in several places so it's good to provide backward support too. This is
# specially true in old embedded systems (OpenWRT and friends) where CMake isn't necessarily upgraded.
# We set it to 2.8.12 as CMake currently indicates that support for versions below it will be removed
# from a future version ("Compatibility with CMake < 2.8.12 will be removed from a future version of CMake.")
# 2.8.12 was released in 2013.
cmake_minimum_required(VERSION 2.8.12)
if(POLICY CMP0048)
cmake_policy(SET CMP0048 NEW)
endif()
# JSON-C library is C only project.
if (CMAKE_VERSION VERSION_LESS 3.0)
project(json-c)
set(PROJECT_VERSION_MAJOR "0")
set(PROJECT_VERSION_MINOR "16")
set(PROJECT_VERSION_PATCH "99")
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
else()
project(json-c LANGUAGES C VERSION 0.16.99)
endif()
# If we've got 3.0 then it's good, let's provide support. Otherwise, leave it be.
if(POLICY CMP0038)
# Policy CMP0038 was introduced in CMake 3.0
cmake_policy(SET CMP0038 NEW)
endif()
if(POLICY CMP0042)
# Policy CMP0042 was introduced in CMake 3.0
# CMake version 3.25.1 warns when the policy is not set and uses OLD behavior
# We set it explicitly to avoid the warning
cmake_policy(SET CMP0042 OLD)
endif()
if(POLICY CMP0054)
cmake_policy(SET CMP0054 NEW)
endif()
# set default build type if not specified by user
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE debug)
endif()
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O2")
# Include file check macros honor CMAKE_REQUIRED_LIBRARIES
# i.e. the check_include_file() calls will include -lm when checking.
if(POLICY CMP0075)
cmake_policy(SET CMP0075 NEW)
endif()
include(CTest)
# Set some packaging variables.
set(CPACK_PACKAGE_NAME "${PROJECT_NAME}")
set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}")
set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}")
set(JSON_C_BUGREPORT "json-c@googlegroups.com")
set(CPACK_SOURCE_IGNORE_FILES
${PROJECT_SOURCE_DIR}/build
${PROJECT_SOURCE_DIR}/cmake-build-debug
${PROJECT_SOURCE_DIR}/pack
${PROJECT_SOURCE_DIR}/.idea
${PROJECT_SOURCE_DIR}/.DS_Store
${PROJECT_SOURCE_DIR}/.git
${PROJECT_SOURCE_DIR}/.vscode)
include(CheckSymbolExists)
include(CheckIncludeFile)
include(CheckIncludeFiles)
include(CheckCSourceCompiles)
include(CheckTypeSize)
include(CPack)
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
option(BUILD_SHARED_LIBS "Default to building shared libraries" ON)
option(BUILD_STATIC_LIBS "Default to building static libraries" ON)
if (BUILD_SHARED_LIBS)
add_definitions(-D JSON_C_DLL)
endif()
# Generate a release merge and test it to verify the correctness of republishing the package.
ADD_CUSTOM_TARGET(distcheck
COMMAND make package_source
COMMAND tar -xvf "${PROJECT_NAME}-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}-Source.tar.gz"
COMMAND mkdir "${PROJECT_NAME}-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}-Source/build"
COMMAND cmake "${PROJECT_NAME}-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}-Source/" -B"./${PROJECT_NAME}-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}-Source/build/"
COMMAND make -C "${PROJECT_NAME}-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}-Source/build"
COMMAND make test -C "${PROJECT_NAME}-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}-Source/build"
COMMAND rm -rf "${PROJECT_NAME}-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}-Source"
)
# Enable or disable features. By default, all features are turned off.
option(DISABLE_BSYMBOLIC "Avoid linking with -Bsymbolic-function." OFF)
option(DISABLE_THREAD_LOCAL_STORAGE "Disable using Thread-Local Storage (HAVE___THREAD)." OFF)
option(DISABLE_WERROR "Avoid treating compiler warnings as fatal errors." OFF)
option(ENABLE_RDRAND "Enable RDRAND Hardware RNG Hash Seed." OFF)
option(ENABLE_THREADING "Enable partial threading support." OFF)
option(OVERRIDE_GET_RANDOM_SEED "Override json_c_get_random_seed() with custom code." OFF)
option(DISABLE_EXTRA_LIBS "Avoid linking against extra libraries, such as libbsd." OFF)
option(DISABLE_JSON_POINTER "Disable JSON pointer (RFC6901) support." OFF)
if (UNIX OR MINGW OR CYGWIN)
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
endif()
if (UNIX)
list(APPEND CMAKE_REQUIRED_LIBRARIES m)
endif()
if (MSVC)
list(APPEND CMAKE_REQUIRED_DEFINITIONS /D_CRT_SECURE_NO_DEPRECATE)
list(APPEND CMAKE_REQUIRED_FLAGS /wd4996)
endif()
if (NOT DISABLE_STATIC_FPIC)
# Use '-fPIC'/'-fPIE' option.
# This will allow other libraries to statically link in libjson-c.a
# which in turn prevents crashes in downstream apps that may use
# a different JSON library with identical symbol names.
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()
check_include_file("fcntl.h" HAVE_FCNTL_H)
check_include_file("inttypes.h" HAVE_INTTYPES_H)
check_include_file(stdarg.h HAVE_STDARG_H)
check_include_file(strings.h HAVE_STRINGS_H)
check_include_file(string.h HAVE_STRING_H)
check_include_file(syslog.h HAVE_SYSLOG_H)
check_include_files("stdlib.h;stdarg.h;string.h;float.h" STDC_HEADERS)
check_include_file(unistd.h HAVE_UNISTD_H)
check_include_file(sys/types.h HAVE_SYS_TYPES_H)
check_include_file(sys/resource.h HAVE_SYS_RESOURCE_H) # for getrusage
check_include_file("dlfcn.h" HAVE_DLFCN_H)
check_include_file("endian.h" HAVE_ENDIAN_H)
check_include_file("limits.h" HAVE_LIMITS_H)
check_include_file("locale.h" HAVE_LOCALE_H)
check_include_file("memory.h" HAVE_MEMORY_H)
check_include_file(stdint.h HAVE_STDINT_H)
check_include_file(stdlib.h HAVE_STDLIB_H)
check_include_file(sys/cdefs.h HAVE_SYS_CDEFS_H)
check_include_file(sys/param.h HAVE_SYS_PARAM_H)
check_include_file(sys/random.h HAVE_SYS_RANDOM_H)
check_include_file(sys/stat.h HAVE_SYS_STAT_H)
check_include_file(xlocale.h HAVE_XLOCALE_H)
if (HAVE_INTTYPES_H)
# Set a json-c specific var to stamp into json_config.h
# in a way that hopefully won't conflict with other
# projects that use json-c.
set(JSON_C_HAVE_INTTYPES_H 1)
endif()
check_symbol_exists(_isnan "float.h" HAVE_DECL__ISNAN)
check_symbol_exists(_finite "float.h" HAVE_DECL__FINITE)
if ((MSVC AND NOT (MSVC_VERSION LESS 1800)) OR MINGW OR CYGWIN OR UNIX)
check_symbol_exists(INFINITY "math.h" HAVE_DECL_INFINITY)
check_symbol_exists(isinf "math.h" HAVE_DECL_ISINF)
check_symbol_exists(isnan "math.h" HAVE_DECL_ISNAN)
check_symbol_exists(nan "math.h" HAVE_DECL_NAN)
endif()
check_symbol_exists(_doprnt "stdio.h" HAVE_DOPRNT)
if (UNIX OR MINGW OR CYGWIN)
check_symbol_exists(snprintf "stdio.h" HAVE_SNPRINTF)
endif()
check_symbol_exists(vasprintf "stdio.h" HAVE_VASPRINTF)
check_symbol_exists(vsnprintf "stdio.h" HAVE_VSNPRINTF)
check_symbol_exists(vprintf "stdio.h" HAVE_VPRINTF)
check_symbol_exists(arc4random "stdlib.h" HAVE_ARC4RANDOM)
if (NOT HAVE_ARC4RANDOM AND DISABLE_EXTRA_LIBS STREQUAL "OFF")
check_include_file(bsd/stdlib.h HAVE_BSD_STDLIB_H)
if (HAVE_BSD_STDLIB_H)
list(APPEND CMAKE_REQUIRED_LIBRARIES "bsd")
unset(HAVE_ARC4RANDOM CACHE)
check_symbol_exists(arc4random "bsd/stdlib.h" HAVE_ARC4RANDOM)
if (NOT HAVE_ARC4RANDOM)
list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES "bsd")
endif()
endif()
endif()
if (HAVE_FCNTL_H)
check_symbol_exists(open "fcntl.h" HAVE_OPEN)
endif()
if (HAVE_STDLIB_H)
check_symbol_exists(realloc "stdlib.h" HAVE_REALLOC)
endif()
if (HAVE_LOCALE_H)
check_symbol_exists(setlocale "locale.h" HAVE_SETLOCALE)
check_symbol_exists(uselocale "locale.h" HAVE_USELOCALE)
endif()
# uClibc *intentionally* crashes in duplocale(), at least as of:
# https://github.com/ffainelli/uClibc/blob/266bdc1/libc/misc/locale/locale.c#L1322
# So, if it looks like we're compiling for a system like that just disable
# locale handling entirely.
exec_program(${CMAKE_C_COMPILER} ARGS -dumpmachine OUTPUT_VARIABLE CMAKE_GNU_C_MACHINE)
if (CMAKE_GNU_C_MACHINE MATCHES "uclibc")
message(STATUS "Detected uClibc compiler, disabling locale handling")
set(HAVE_SETLOCALE 0)
set(HAVE_USELOCALE 0)
endif()
if (HAVE_STRINGS_H)
check_symbol_exists(strcasecmp "strings.h" HAVE_STRCASECMP)
check_symbol_exists(strncasecmp "strings.h" HAVE_STRNCASECMP)
endif()
if (HAVE_STRING_H)
check_symbol_exists(strdup "string.h" HAVE_STRDUP)
check_symbol_exists(strerror "string.h" HAVE_STRERROR)
endif()
if (HAVE_SYSLOG_H)
check_symbol_exists(vsyslog "syslog.h" HAVE_VSYSLOG)
endif()
if (HAVE_SYS_RANDOM_H)
check_symbol_exists(getrandom "sys/random.h" HAVE_GETRANDOM)
endif()
if (HAVE_SYS_RESOURCE_H)
check_symbol_exists(getrusage "sys/resource.h" HAVE_GETRUSAGE)
endif()
check_symbol_exists(strtoll "stdlib.h" HAVE_STRTOLL)
check_symbol_exists(strtoull "stdlib.h" HAVE_STRTOULL)
set(json_c_strtoll "strtoll")
if (NOT HAVE_STRTOLL)
# Use _strtoi64 if strtoll is not available.
check_symbol_exists(_strtoi64 "stdlib.h" __have_strtoi64)
if (__have_strtoi64)
#set(HAVE_STRTOLL 1)
set(json_c_strtoll "_strtoi64")
endif()
endif()
set(json_c_strtoull "strtoull")
if (NOT HAVE_STRTOULL)
# Use _strtoui64 if strtoull is not available.
check_symbol_exists(_strtoui64 "stdlib.h" __have_strtoui64)
if (__have_strtoui64)
#set(HAVE_STRTOULL 1)
set(json_c_strtoull "_strtoui64")
endif()
endif()
check_type_size(int SIZEOF_INT)
check_type_size(int64_t SIZEOF_INT64_T)
check_type_size(long SIZEOF_LONG)
check_type_size("long long" SIZEOF_LONG_LONG)
check_type_size("size_t" SIZEOF_SIZE_T)
if (MSVC)
list(APPEND CMAKE_EXTRA_INCLUDE_FILES BaseTsd.h)
check_type_size("SSIZE_T" SIZEOF_SSIZE_T)
else()
check_type_size("ssize_t" SIZEOF_SSIZE_T)
endif()
check_c_source_compiles(
"
extern void json_object_get();
__asm__(\".section .gnu.json_object_get\\n\\t.ascii \\\"Please link against libjson-c instead of libjson\\\"\\n\\t.text\");
int main(int c, char *v) { return 0;}
"
HAS_GNU_WARNING_LONG)
check_c_source_compiles(
"int main() { int i, x = 0; i = __sync_add_and_fetch(&x,1); return x; }"
HAVE_ATOMIC_BUILTINS)
if (NOT DISABLE_THREAD_LOCAL_STORAGE)
check_c_source_compiles(
"__thread int x = 0; int main() { return 0; }"
HAVE___THREAD)
if (HAVE___THREAD)
set(SPEC___THREAD __thread)
elseif (MSVC)
set(SPEC___THREAD __declspec(thread))
endif()
endif()
# Hardware random number is not available on Windows? Says, config.h.win32. Best to preserve compatibility.
if (WIN32)
set(ENABLE_RDRAND 0)
endif()
# Once we've done basic symbol/header searches let's add them in.
configure_file(${PROJECT_SOURCE_DIR}/cmake/config.h.in ${PROJECT_BINARY_DIR}/config.h)
message(STATUS "Wrote ${PROJECT_BINARY_DIR}/config.h")
configure_file(${PROJECT_SOURCE_DIR}/cmake/json_config.h.in ${PROJECT_BINARY_DIR}/json_config.h)
message(STATUS "Wrote ${PROJECT_BINARY_DIR}/json_config.h")
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections")
if ("${DISABLE_WERROR}" STREQUAL "OFF")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wcast-qual")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error=deprecated-declarations")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wextra")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wwrite-strings")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-parameter")
if (NOT WIN32)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wstrict-prototypes")
endif()
add_definitions(-D_GNU_SOURCE)
elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /DEBUG")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4100")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4996")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4244")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4706")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4702")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4127")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4701")
endif()
if (NOT ("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC"))
check_c_source_compiles(
"
/* uClibc toolchains without threading barf when _REENTRANT is defined */
#define _REENTRANT 1
#include <sys/types.h>
int main (void)
{
return 0;
}
"
REENTRANT_WORKS
)
if (REENTRANT_WORKS)
add_compile_options("-D_REENTRANT")
endif()
# OSX Mach-O doesn't support linking with '-Bsymbolic-functions'.
# Others may not support it, too.
list(APPEND CMAKE_REQUIRED_LIBRARIES "-Wl,-Bsymbolic-functions")
check_c_source_compiles(
"
int main (void)
{
return 0;
}
"
BSYMBOLIC_WORKS
)
list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES "-Wl,-Bsymbolic-functions")
if (DISABLE_BSYMBOLIC STREQUAL "OFF" AND BSYMBOLIC_WORKS)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-Bsymbolic-functions")
# XXX need cmake>=3.13 for this:
#add_link_options("-Wl,-Bsymbolic-functions")
endif()
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/check-version-script.sym" "TEST { global: *; };")
list(APPEND CMAKE_REQUIRED_LIBRARIES "-Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/check-version-script.sym")
check_c_source_compiles(
"
int main (void)
{
return 0;
}
"
VERSION_SCRIPT_WORKS
)
list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES "-Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/check-version-script.sym")
if (VERSION_SCRIPT_WORKS)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--version-script,${CMAKE_CURRENT_SOURCE_DIR}/json-c.sym")
endif()
endif()
if ($ENV{VALGRIND})
# Build so that valgrind doesn't complain about linkhash.c
add_definitions(-DVALGRIND=1)
endif()
set(JSON_C_PUBLIC_HEADERS
# Note: config.h is _not_ included here
${PROJECT_BINARY_DIR}/json_config.h
${PROJECT_BINARY_DIR}/json.h
${PROJECT_SOURCE_DIR}/arraylist.h
${PROJECT_SOURCE_DIR}/debug.h
${PROJECT_SOURCE_DIR}/json_c_version.h
${PROJECT_SOURCE_DIR}/json_inttypes.h
${PROJECT_SOURCE_DIR}/json_object.h
${PROJECT_SOURCE_DIR}/json_object_iterator.h
${PROJECT_SOURCE_DIR}/json_tokener.h
${PROJECT_SOURCE_DIR}/json_types.h
${PROJECT_SOURCE_DIR}/json_util.h
${PROJECT_SOURCE_DIR}/json_visit.h
${PROJECT_SOURCE_DIR}/linkhash.h
${PROJECT_SOURCE_DIR}/printbuf.h
)
set(JSON_C_HEADERS
${JSON_C_PUBLIC_HEADERS}
${PROJECT_SOURCE_DIR}/json_object_private.h
${PROJECT_SOURCE_DIR}/random_seed.h
${PROJECT_SOURCE_DIR}/strerror_override.h
${PROJECT_SOURCE_DIR}/strerror_override_private.h
${PROJECT_SOURCE_DIR}/math_compat.h
${PROJECT_SOURCE_DIR}/snprintf_compat.h
${PROJECT_SOURCE_DIR}/strdup_compat.h
${PROJECT_SOURCE_DIR}/vasprintf_compat.h
)
set(JSON_C_SOURCES
${PROJECT_SOURCE_DIR}/arraylist.c
${PROJECT_SOURCE_DIR}/debug.c
${PROJECT_SOURCE_DIR}/json_c_version.c
${PROJECT_SOURCE_DIR}/json_object.c
${PROJECT_SOURCE_DIR}/json_object_iterator.c
${PROJECT_SOURCE_DIR}/json_tokener.c
${PROJECT_SOURCE_DIR}/json_util.c
${PROJECT_SOURCE_DIR}/json_visit.c
${PROJECT_SOURCE_DIR}/linkhash.c
${PROJECT_SOURCE_DIR}/printbuf.c
${PROJECT_SOURCE_DIR}/random_seed.c
${PROJECT_SOURCE_DIR}/strerror_override.c
)
if (NOT DISABLE_JSON_POINTER)
set(JSON_C_PUBLIC_HEADERS ${JSON_C_PUBLIC_HEADERS} ${PROJECT_SOURCE_DIR}/json_pointer.h)
set(JSON_C_SOURCES ${JSON_C_SOURCES} ${PROJECT_SOURCE_DIR}/json_pointer.c)
set(JSON_H_JSON_POINTER "#include \"json_pointer.h\"")
else()
set(JSON_H_JSON_POINTER "")
endif()
configure_file(json.h.cmakein ${PROJECT_BINARY_DIR}/json.h @ONLY)
include_directories(${PROJECT_SOURCE_DIR})
include_directories(${PROJECT_BINARY_DIR})
add_subdirectory(doc)
# "uninstall" custom target for make generators in unix like operating systems
# and if that target is not present
if (CMAKE_GENERATOR STREQUAL "Unix Makefiles")
if(NOT TARGET uninstall)
add_custom_target(uninstall
COMMAND cat ${PROJECT_BINARY_DIR}/install_manifest.txt | xargs rm
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
endif()
endif()
# XXX for a normal full distribution we'll need to figure out
# XXX how to build both shared and static libraries.
# Probably leverage that to build a local VALGRIND=1 library for testing too.
add_library(${PROJECT_NAME}
${JSON_C_SOURCES}
${JSON_C_HEADERS}
)
set_target_properties(${PROJECT_NAME} PROPERTIES
VERSION 5.2.0
SOVERSION 5)
list(APPEND CMAKE_TARGETS ${PROJECT_NAME})
# If json-c is used as subroject it set to target correct interface -I flags and allow
# to build external target without extra include_directories(...)
target_include_directories(${PROJECT_NAME}
PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>
)
target_link_libraries(${PROJECT_NAME} PUBLIC ${CMAKE_REQUIRED_LIBRARIES})
# Allow to build static and shared libraries at the same time
if (BUILD_STATIC_LIBS AND BUILD_SHARED_LIBS)
set(STATIC_LIB ${PROJECT_NAME}-static)
add_library(${STATIC_LIB} STATIC
${JSON_C_SOURCES}
${JSON_C_HEADERS}
)
target_include_directories(${PROJECT_NAME}-static
PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>
)
target_link_libraries(${PROJECT_NAME}-static PUBLIC ${CMAKE_REQUIRED_LIBRARIES})
# rename the static library
if (NOT MSVC)
set_target_properties(${STATIC_LIB} PROPERTIES
OUTPUT_NAME ${PROJECT_NAME}
)
endif()
list(APPEND CMAKE_TARGETS ${STATIC_LIB})
endif ()
# Always create new install dirs with 0755 permissions, regardless of umask
set(CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
OWNER_READ
OWNER_WRITE
OWNER_EXECUTE
GROUP_READ
GROUP_EXECUTE
WORLD_READ
WORLD_EXECUTE
)
install(TARGETS ${CMAKE_TARGETS}
EXPORT ${PROJECT_NAME}-targets
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ${CMAKE_INSTALL_INCLUDEDIR}/json-c
)
install(EXPORT ${PROJECT_NAME}-targets
FILE ${PROJECT_NAME}-targets.cmake
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
)
configure_package_config_file(
"cmake/Config.cmake.in"
${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
)
install(
FILES ${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
)
if (UNIX OR MINGW OR CYGWIN)
SET(prefix ${CMAKE_INSTALL_PREFIX})
# exec_prefix is prefix by default and CMake does not have the
# concept.
SET(exec_prefix ${CMAKE_INSTALL_PREFIX})
SET(libdir ${CMAKE_INSTALL_FULL_LIBDIR})
SET(includedir ${CMAKE_INSTALL_FULL_INCLUDEDIR})
SET(VERSION ${PROJECT_VERSION})
# Linking against the static json-c requires
# dependent packages to include additional libs:
SET(LIBS_LIST ${CMAKE_REQUIRED_LIBRARIES})
# Note: We would need cmake >= 3.12 in order to use list(TRANSFORM ...)
function(list_transform_prepend var prefix)
set(temp "")
foreach(f ${${var}})
list(APPEND temp "${prefix}${f}")
endforeach()
set(${var} "${temp}" PARENT_SCOPE)
endfunction()
list_transform_prepend(LIBS_LIST "-l")
string(REPLACE ";" " " LIBS "${LIBS_LIST}")
configure_file(json-c.pc.in json-c.pc @ONLY)
set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_LIBDIR}/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files")
install(FILES ${PROJECT_BINARY_DIR}/json-c.pc DESTINATION "${INSTALL_PKGCONFIG_DIR}")
endif ()
install(FILES ${JSON_C_PUBLIC_HEADERS} DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR}/json-c)
if (CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING AND
(NOT MSVC OR NOT (MSVC_VERSION LESS 1800)) # Tests need at least VS2013
)
add_subdirectory(tests)
endif()
if (NOT MSVC) # cmd line apps don't built on Windows currently.
add_subdirectory(apps)
endif()

42
thirdparty/json-c/COPYING vendored Normal file
View File

@@ -0,0 +1,42 @@
Copyright (c) 2009-2012 Eric Haszlakiewicz
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
----------------------------------------------------------------
Copyright (c) 2004, 2005 Metaparadigm Pte Ltd
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

605
thirdparty/json-c/ChangeLog vendored Normal file
View File

@@ -0,0 +1,605 @@
0.17 (future release)
========================================
Deprecated and removed features:
--------------------------------
* ...
New features
------------
* ...
Significant changes and bug fixes
---------------------------------
* When serializing with JSON_C_TO_STRING_PRETTY set, keep the opening and
closing curly or square braces on same line for empty objects or arrays.
* Disable locale handling when targeting a uClibc system due to problems
with its duplocale() function.
* When parsing with JSON_TOKENER_STRICT set, integer overflow/underflow
now result in a json_tokener_error_parse_number. Without that flag
values are capped at INT64_MIN/UINT64_MAX.
0.16 (up to commit 66dcdf5, 2022-04-13)
========================================
Deprecated and removed features:
--------------------------------
* JSON_C_OBJECT_KEY_IS_CONSTANT is deprecated in favor of
JSON_C_OBJECT_ADD_CONSTANT_KEY
* Direct access to lh_table and lh_entry structure members is deprecated.
Use access functions instead, lh_table_head(), lh_entry_next(), etc...
* Drop REFCOUNT_DEBUG code.
New features
------------
* The 0.16 release introduces no new features
Build changes
-------------
* Add a DISABLE_EXTRA_LIBS option to skip using libbsd
* Add a DISABLE_JSON_POINTER option to skip compiling in json_pointer support.
Significant changes and bug fixes
---------------------------------
* Cap string length at INT_MAX to avoid various issues with very long strings.
* json_object_deep_copy: fix deep copy of strings containing '\0'
* Fix read past end of buffer in the "json_parse" command
* Avoid out of memory accesses in the locally provided vasprintf() function
(for those platforms that use it)
* Handle allocation failure in json_tokener_new_ex
* Fix use-after-free in json_tokener_new_ex() in the event of printbuf_new() returning NULL
* printbuf_memset(): set gaps to zero - areas within the print buffer which
have not been initialized by using printbuf_memset
* printbuf: return -1 on invalid arguments (len < 0 or total buffer > INT_MAX)
* sprintbuf(): propagate printbuf_memappend errors back to the caller
Optimizations
--------------
* Speed up parsing by replacing ctype functions with simplified, faster
non-locale-sensitive ones in json_tokener and json_object_to_json_string.
* Neither vertical tab nor formfeed are considered whitespace per the JSON spec
* json_object: speed up creation of objects, calloc() -> malloc() + set fields
* Avoid needless extra strlen() call in json_c_shallow_copy_default() and
json_object_equal() when the object is known to be a json_type_string.
Other changes
-------------
* Validate size arguments in arraylist functions.
* Use getrandom() if available; with GRND_NONBLOCK to allow use of json-c
very early during boot, such as part of cryptsetup.
* Use arc4random() if it's available.
* random_seed: on error, continue to next method instead of exiting the process
* Close file when unable to read from /dev/urandom in get_dev_random_seed()
***
0.15 (up to commit 870965e, 2020/07/26)
========================================
Deprecated and removed features:
--------------------------------
* Deprecate `array_list_new()` in favor of `array_list_new2()`
* Remove the THIS_FUNCTION_IS_DEPRECATED define.
* Remove config.h.win32
New features
------------
* Add a `JSON_TOKENER_ALLOW_TRAILING_CHARS` flag to allow multiple objects
to be parsed even when `JSON_TOKENER_STRICT` is set.
* Add `json_object_new_array_ext(int)` and `array_list_new_2(int)` to allow
arrays to be allocated with the exact size needed, when known.
* Add `json_object_array_shrink()` (and `array_list_shrink()`) and use it in
json_tokener to minimize the amount of memory used.
* Add a json_parse binary, for use in testing changes (not installed, but
available in the apps directory).
Build changes
-------------
* #639/#621 - Add symbol versions to all exported symbols
* #508/#634 - Always enable -fPIC to allow use of the json-c static library in
other libraries
* Build both static and shared libraries at the same time.
* #626 - Restore compatibility with cmake 2.8
* #471 - Always create directories with mode 0755, regardless of umask.
* #606/#604 - Improve support for OSes like AIX and IBM i, as well as for
MINGW32 and old versions of MSVC
* #451/#617 - Add a DISABLE_THREAD_LOCAL_STORAGE cmake option to disable
the use of thread-local storage.
Significant changes and bug fixes
---------------------------------
* Split the internal json_object structure into several sub-types, one for
each json_type (json_object_object, json_object_string, etc...).
This improves memory usage and speed, with the benchmark under
bench/ report 5.8% faster test time and 6%(max RSS)-12%(peak heap)
less memory usage.
Memory used just for json_object structures decreased 27%, so use cases
with fewer arrays and/or strings would benefit more.
* Minimize memory usage in array handling in json_tokener by shrinking
arrays to the exact number of elements parsed. On bench/ benchmark:
9% faster test time, 39%(max RSS)-50%(peak heap) less memory usage.
Add json_object_array_shrink() and array_list_shrink() functions.
* #616 - Parsing of surrogate pairs in unicode escapes now properly handles
incremental parsing.
* Fix incremental parsing of numbers, especially those with exponents, e.g.
so parsing "[0", "e+", "-]" now properly returns an error.
Strict mode now rejects missing exponents ("0e").
* Successfully return number objects at the top level even when they are
followed by a "-", "." or "e". This makes parsing things like "123-45"
behave consistently with things like "123xyz".
Other changes
-------------
* #589 - Detect broken RDRAND during initialization; also, fix segfault
in the CPUID check.
* #592 - Fix integer overflows to prevert out of bounds write on large input.
* Protect against division by zero in linkhash, when created with zero size.
* #602 - Fix json_parse_uint64() internal error checking, leaving the retval
untouched in more failure cases.
* #614 - Prevent truncation when custom double formatters insert extra \0's
***
0.14 (up to commit 9ed00a6, 2020/04/14)
=========================================
Deprecated and removed features:
--------------------------------
* bits.h has been removed
* lh_abort() has been removed
* lh_table_lookup() has been removed, use lh_table_lookup_ex() instead.
* Remove TRUE and FALSE defines, use 1 and 0 instead.
Build changes:
--------------
## Deprecated and removed features:
* bits.h has been removed
* lh_abort() has been removed
* lh_table_lookup() has been removed, use lh_table_lookup_ex() instead.
* Remove TRUE and FALSE defines, use 1 and 0 instead.
* autoconf support, including autogen.sh, has been removed. See details about cmake, below.
* With the addition of json_tokener_get_parse_end(), access to internal fields of json_tokener, as well as use of many other symbols and types in json_tokener.h, is deprecated now.
* The use of Android.configure.mk to build for Android no longer works, and it is unknown how (or if) the new cmake-based build machinery can be used.
* Reports of success, or pull requests to correct issues are welcome.
## Notable improvements and new features
### Builds and documentation
* Build machinery has been switched to CMake. See README.md for details about how to build.
* TL;DR: `mkdir build ; cd build ; cmake -DCMAKE_INSTALL_PREFIX=/some/path ../json-c ; make all test install`
* To ease the transition, there is a `cmake-configure` wrapper that emulates the old autoconf-based configure script.
* This has enabled improvements to the build on Windows system; also all public functions have been fixed to be properly exported. For best results, use Visual Studio 2015 or newer.
* The json-c style guide has been updated to specify the use of clang-format, and all code has been reformatted.
* Since many lines of code have trivial changes now, when using git blame, be sure to specify -w
* Numerous improvements have been made to the documentation including function effects on refcounts, when passing a NULL is safe, and so on.
### json_tokener changes
* Added a json_tokener_get_parse_end() function to replace direct access of tok->char_offset.
* The char_offset field, and the rest of the json_tokener structure remain exposed for now, but expect a future release to hide it like is done with json_object_private.h
* json_tokener_parse_ex() now accepts a new JSON_TOKENER_VALIDATE_UTF8 flag to validate that input is UTF8.
* If validation fails, json_tokener_get_error(tok) will return json_tokener_error_parse_utf8_string (see enum json_tokener_error).
### Other changes and additions
* Add support for unsigned 64-bit integers, uint64_t, to gain one extra bit of magnitude for positive ints.
* json_tokener will now parse values up to UINT64_MAX (18446744073709551615)
* Existing methods returning int32_t or int64_t will cap out-of-range values at INT32_MAX or INT64_MAX, preserving existing behavior.
* The implementation includes the possibility of easily extending this to larger sizes in the future.
* A total of 7 new functions were added:
* json_object_get_uint64 ( struct json_object const* jso )
* json_object_new_uint64 ( uint64_t i )
* json_object_set_uint64 ( struct json_object* jso, uint64_t new_value )
* json_parse_uint64 ( char const* buf, uint64_t* retval )
* See description of uint64 support, above.
* json_tokener_get_parse_end ( struct json_tokener* tok )
* See details under "json_tokener changes", above.
* json_object_from_fd_ex ( int fd, int in_depth )
* Allows the max nesting depth to be specified.
* json_object_new_null ( )
* Simply returns NULL. Its use is not recommended.
* The size of struct json_object has decreased from 96 bytes to 88 bytes.
### Testing
* Many updates were made to test cases, increasing code coverage.
* There is now a quick way (JSONC_TEST_TRACE=1) to turn on shell tracing in tests.
* To run tests, use `make test`; the old "check" target no longer exists.
## Significant bug fixes
For the full list of issues and pull requests since the previous release, please see issues_closed_for_0.14.md
* [Issue #389](https://github.com/json-c/json-c/issues/389): Add an assert to explicitly crash when _ref_count is corrupted, instead of a later "double free" error.
* [Issue #407](https://github.com/json-c/json-c/issues/407): fix incorrect casts in calls to ctype functions (isdigit and isspace) so we don't crash when asserts are enabled on certain platforms and characters > 128 are parsed.
* [Issue #418](https://github.com/json-c/json-c/issues/418): Fix docs for json_util_from_fd and json_util_from_file to say that they return NULL on failures.
* [Issue #422](https://github.com/json-c/json-c/issues/422): json_object.c:set errno in json_object_get_double() when called on a json_type_string object with bad content.
* [Issue #453](https://github.com/json-c/json-c/issues/453): Fixed misalignment in JSON serialization when JSON_C_TO_STRING_SPACED and JSON_C_TO_STRING_PRETTY are used together.
* [Issue #463](https://github.com/json-c/json-c/issues/463): fix newlocale() call to use LC_NUMERIC_MASK instead of LC_NUMERIC, and remove incorrect comment.
* [Issue #486](https://github.com/json-c/json-c/issues/486): append a missing ".0" to negative double values to ensure they are serialized as floating point numbers.
* [Issue #488](https://github.com/json-c/json-c/issues/488): use JSON_EXPORT on functions so they are properly exported on Windows.
* [Issue #539](https://github.com/json-c/json-c/issues/539): use an internal-only serializer function in json_object_new_double_s() to avoid potential conflicts with user code that uses the json_object_userdata_to_json_string serializer.
***
0.13.1 (up to commit 0f814e5, 2018/03/04)
=========================================
* Bump the major version of the .so library generated up to 4.0 to avoid
conflicts because some downstream packagers of json-c had already done
their own bump to ".so.3" for a much older 0.12 release.
* Add const size_t json_c_object_sizeof()
* Avoid invalid free (and thus a segfault) when ref_count gets < 0
* PR#394: fix handling of custom double formats that include a ".0"
* Avoid uninitialized variable warnings in json_object_object_foreach
* Issue #396: fix build for certain uClibc based systems.
* Add a top level fuzz directory for fuzzers run by OSS-Fuzz
0.13 (up to commit 5dae561, 2017/11/29)
=================================
This release, being three and a half years after the 0.12 branch (f84d9c),
has quite a number of changes included. The following is a sampling of
the most significant ones.
Since the 0.12 release, 250 issues and pull requests have been closed.
See issues_closed_for_0.13.md for a complete list.
Deprecated and removed features:
--------------------------------
* All internal use of bits.h has been eliminated. The file will be removed.
Do not use: hexdigit(), error_ptr(), error_descrition() and it_error()
* lh_abort() is deprecated. It will be removed.
Behavior changes:
-----------------
* Tighten the number parsing algorithm to raise errors instead of truncating
the results. For example 12.3.4 or 2015-01-15, which now return null.
See commit 99d8fc
* Use size_t for array length and size. Platforms where sizeof(size_t) != sizeof(int) may not be backwards compatible
See commits 45c56b, 92e9a5 and others.
* Check for failure when allocating memory, returning NULL and errno=ENOMEM.
See commit 2149a04.
* Change json_object_object_add() return type from void to int, and will return -1 on failures, instead of exiting. (Note: this is not an ABI change)
New features:
-------------
* We're aiming to follow RFC 7159 now.
* Add a couple of additional option to json_object_to_json_string_ext:
JSON_C_TO_STRING_PRETTY_TAB
JSON_C_TO_STRING_NOSLASHESCAPE
* Add a json_object_object_add_ex() function to allow for performance
improvements when certain constraints are known to be true.
* Make serialization format of doubles configurable, in two different ways:
Call json_object_set_serializer with json_object_double_to_json_string and a custom
format on each double object, or
Call json_c_set_serialization_double_format() to set a global or thread-wide format.
* Add utility function for comparing json_objects - json_object_equal()
* Add a way to copy entire object trees: json_object_deep_copy()
* Add json_object_set_<type> function to modify the value of existing json_object's
without the need to recreate them. Also add a json_object_int_inc function to
adjust an int's value.
* Add support for JSON pointer, RFC 6901. See json_pointer.h
* Add a json_util_get_last_err() function to retrieve the string describing the
cause of errors, instead of printing to stderr.
* Add perllike hash function for strings, and json_global_set_string_hash() 8f8d03d
* Add a json_c_visit() function to provide a way to iterate over a tree of json-c objects.
Notable bug fixes and other improvements:
-----------------------------------------
* Make reference increment and decrement atomic to allow passing json objects between threads.
* Fix json_object_object_foreach to avoid uninitialized variable warnings.
* Improve performance by removing unneeded data items from hashtable code and reducing duplicate hash computation.
* Improve performance by storing small strings inside json_object
* Improve performance of json_object_to_json_string by removing variadic printf. commit 9ff0f49
* Issue #371: fix parsing of "-Infinity", and avoid needlessly copying the input when doing so.
* Fix stack buffer overflow in json_object_double_to_json_string_format() - commit 2c2deb87
* Fix various potential null ptr deref and int32 overflows
* Issue #332: fix a long-standing bug in array_list_put_idx() where it would attempt to free previously free'd entries due to not checking the current array length.
* Issue #195: use uselocale() instead of setlocale() in json_tokener to behave better in threaded environments.
* Issue #275: fix out of bounds read when handling unicode surrogate pairs.
* Ensure doubles that happen to be a whole number are emitted with ".0" - commit ca7a19
* PR#331: for Visual Studio, use a snprintf/vsnprintf wrapper that ensures the string is terminated.
* Fix double to int cast overflow in json_object_get_int64.
* Clamp double to int32 when narrowing in json_object_get_int.
* Use strtoll() to parse ints - instead of sscanf
* Miscellaneous smaller changes, including removing unused variables, fixing warning
about uninitialized variables adding const qualifiers, reformatting code, etc...
Build changes:
--------------
* Add Appveyor and Travis build support
* Switch to using CMake when building on Windows with Visual Studio.
A dynamic .dll is generated instead of a .lib
config.h is now generated, config.h.win32 should no longer be manually copied
* Add support for MacOS through CMake too.
* Enable silent build by default
* Link against libm when needed
* Add support for building with AddressSanitizer
* Add support for building with Clang
* Add a --enable-threading configure option, and only use the (slower) __sync_add_and_fetch()/__sync_sub_and_fetch() function when it is specified.
List of new functions added:
----------------------------
### json_object.h
* array_list_bsearch()
* array_list_del_idx()
* json_object_to_json_string_length()
* json_object_get_userdata()
* json_object_set_userdata()
* json_object_object_add_ex()
* json_object_array_bsearch()
* json_object_array_del_idx()
* json_object_set_boolean()
* json_object_set_int()
* json_object_int_inc()
* json_object_set_int64()
* json_c_set_serialization_double_format()
* json_object_double_to_json_string()
* json_object_set_double()
* json_object_set_string()
* json_object_set_string_len()
* json_object_equal()
* json_object_deep_copy()
### json_pointer.h
* json_pointer_get()
* json_pointer_getf()
* json_pointer_set()
* json_pointer_setf()
### json_util.h
* json_object_from_fd()
* json_object_to_fd()
* json_util_get_last_err()
### json_visit.h
* json_c_visit()
### linkhash.h
* json_global_set_string_hash()
* lh_table_resize()
### printbuf.h
* printbuf_strappend()
0.12.1
======
* Minimal changes to address compile issues.
0.12
====
* Address security issues:
* CVE-2013-6371: hash collision denial of service
* CVE-2013-6370: buffer overflow if size_t is larger than int
* Avoid potential overflow in json_object_get_double
* Eliminate the mc_abort() function and MC_ABORT macro.
* Make the json_tokener_errors array local. It has been deprecated for
a while, and json_tokener_error_desc() should be used instead.
* change the floating point output format to %.17g so values with
more than 6 digits show up in the output.
* Remove the old libjson.so name compatibility support. The library is
only created as libjson-c.so now and headers are only installed
into the ${prefix}/json-c directory.
* When supported by the linker, add the -Bsymbolic-functions flag.
* Various changes to fix the build on MSVC.
* Make strict mode more strict:
* number must not start with 0
* no single-quote strings
* no comments
* trailing char not allowed
* only allow lowercase literals
* Added a json_object_new_double_s() convenience function to allow
an exact string representation of a double to be specified when
creating the object and use it in json_tokener_parse_ex() so
a re-serialized object more exactly matches the input.
* Add support NaN and Infinity
0.11
====
* IMPORTANT: the name of the library has changed to libjson-c.so and
the header files are now in include/json-c.
The pkgconfig name has also changed from json to json-c.
You should change your build to use appropriate -I and -l options.
A compatibility shim is in place so builds using the old name will
continue to work, but that will be removed in the next release.
* Maximum recursion depth is now a runtime option.
json_tokener_new() is provided for compatibility.
json_tokener_new_ex(depth)
* Include json_object_iterator.h in the installed headers.
* Add support for building on Android.
* Rewrite json_object_object_add to replace just the value if the key already exists so keys remain valid.
* Make it safe to delete keys while iterating with the json_object_object_foreach macro.
* Add a json_set_serializer() function to allow the string output of a json_object to be customized.
* Make float parsing locale independent.
* Add a json_tokener_set_flags() function and a JSON_TOKENER_STRICT flag.
* Enable -Werror when building.
* speed improvements to parsing 64-bit integers on systems with working sscanf
* Add a json_object_object_length function.
* Fix a bug (buffer overrun) when expanding arrays to more than 64 entries.
0.10
====
* Add a json_object_to_json_string_ext() function to allow output to be
formatted in a more human readable form.
* Add json_object_object_get_ex(), a NULL-safe get object method, to be able
to distinguish between a key not present and the value being NULL.
* Add an alternative iterator implementation, see json_object_iterator.h
* Make json_object_iter public to enable external use of the
json_object_object_foreachC macro.
* Add a printbuf_memset() function to provide an efficient way to set and
append things like whitespace indentation.
* Adjust json_object_is_type and json_object_get_type so they return
json_type_null for NULL objects and handle NULL passed to
json_objct_object_get().
* Rename boolean type to json_bool.
* Fix various compile issues for Visual Studio and MinGW.
* Allow json_tokener_parse_ex() to be re-used to parse multiple object.
Also, fix some parsing issues with capitalized hexadecimal numbers and
number in E notation.
* Add json_tokener_get_error() and json_tokener_error_desc() to better
encapsulate the process of retrieving errors while parsing.
* Various improvements to the documentation of many functions.
* Add new json_object_array_sort() function.
* Fix a bug in json_object_get_int(), which would incorrectly return 0
when called on a string type object.
Eric Haszlakiewicz
* Add a json_type_to_name() function.
Eric Haszlakiewicz
* Add a json_tokener_parse_verbose() function.
Jehiah Czebotar
* Improve support for null bytes within JSON strings.
Jehiah Czebotar
* Fix file descriptor leak if memory allocation fails in json_util
Zachary Blair, zack_blair at hotmail dot com
* Add int64 support. Two new functions json_object_net_int64 and
json_object_get_int64. Binary compatibility preserved.
Eric Haszlakiewicz, EHASZLA at transunion com
Rui Miguel Silva Seabra, rms at 1407 dot org
* Fix subtle bug in linkhash where lookup could hang after all slots
were filled then successively freed.
Spotted by Jean-Marc Naud, j dash m at newtraxtech dot com
* Make json_object_from_file take const char *filename
Spotted by Vikram Raj V, vsagar at attinteractive dot com
* Add handling of surrogate pairs (json_tokener.c, test4.c, Makefile.am)
Brent Miller, bdmiller at yahoo dash inc dot com
* Correction to comment describing printbuf_memappend in printbuf.h
Brent Miller, bdmiller at yahoo dash inc dot com
0.9
===
* Add README.html README-WIN32.html config.h.win32 to Makefile.am
Michael Clark, <michael@metaparadigm.com>
* Add const qualifier to the json_tokener_parse functions
Eric Haszlakiewicz, EHASZLA at transunion dot com
* Rename min and max so we can never clash with C or C++ std library
Ian Atha, thatha at yahoo dash inc dot com
* Fix any noticeable spelling or grammar errors.
* Make sure every va_start has a va_end.
* Check all pointers for validity.
Erik Hovland, erik at hovland dot org
* Fix json_object_get_boolean to return false for empty string
Spotted by Vitaly Kruglikov, Vitaly dot Kruglikov at palm dot com
* optimizations to json_tokener_parse_ex(), printbuf_memappend()
Brent Miller, bdmiller at yahoo dash inc dot com
* Disable REFCOUNT_DEBUG by default in json_object.c
* Don't use this as a variable, so we can compile with a C++ compiler
* Add casts from void* to type of assignment when using malloc
* Add #ifdef __cplusplus guards to all of the headers
* Add typedefs for json_object, json_tokener, array_list, printbuf, lh_table
Michael Clark, <michael@metaparadigm.com>
* Null pointer dereference fix. Fix json_object_get_boolean strlen test
to not return TRUE for zero length string. Remove redundant includes.
Erik Hovland, erik at hovland dot org
* Fixed warning reported by adding -Wstrict-prototypes
-Wold-style-definition to the compilatin flags.
Dotan Barak, dotanba at gmail dot com
* Add const correctness to public interfaces
Gerard Krol, g dot c dot krol at student dot tudelft dot nl
0.8
===
* Add va_end for every va_start
Dotan Barak, dotanba at gmail dot com
* Add macros to enable compiling out debug code
Geoffrey Young, geoff at modperlcookbook dot org
* Fix bug with use of capital E in numbers with exponents
Mateusz Loskot, mateusz at loskot dot net
* Add stddef.h include
* Patch allows for json-c compile with -Werror and not fail due to
-Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
Geoffrey Young, geoff at modperlcookbook dot org
0.7
===
* Add escaping of backslash to json output
* Add escaping of forward slash on tokenizing and output
* Changes to internal tokenizer from using recursion to
using a depth state structure to allow incremental parsing
0.6
===
* Fix bug in escaping of control characters
Johan Björklund, johbjo09 at kth dot se
* Remove include "config.h" from headers (should only
be included from .c files)
Michael Clark <michael@metaparadigm.com>
0.5
===
* Make headers C++ compatible by change *this to *obj
* Add ifdef C++ extern "C" to headers
* Use simpler definition of min and max in bits.h
Larry Lansing, llansing at fuzzynerd dot com
* Remove automake 1.6 requirement
* Move autogen commands into autogen.sh. Update README
* Remove error pointer special case for Windows
* Change license from LGPL to MIT
Michael Clark <michael@metaparadigm.com>
0.4
===
* Fix additional error case in object parsing
* Add back sign reversal in nested object parse as error pointer
value is negative, while error value is positive.
Michael Clark <michael@metaparadigm.com>
0.3
===
* fix pointer arithmetic bug for error pointer check in is_error() macro
* fix type passed to printbuf_memappend in json_tokener
* update autotools bootstrap instructions in README
Michael Clark <michael@metaparadigm.com>
0.2
===
* printbuf.c - C. Watford (christopher.watford@gmail.com)
Added a Win32/Win64 compliant implementation of vasprintf
* debug.c - C. Watford (christopher.watford@gmail.com)
Removed usage of vsyslog on Win32/Win64 systems, needs to be handled
by a configure script
* json_object.c - C. Watford (christopher.watford@gmail.com)
Added scope operator to wrap usage of json_object_object_foreach, this
needs to be rethought to be more ANSI C friendly
* json_object.h - C. Watford (christopher.watford@gmail.com)
Added Microsoft C friendly version of json_object_object_foreach
* json_tokener.c - C. Watford (christopher.watford@gmail.com)
Added a Win32/Win64 compliant implementation of strndup
* json_util.c - C. Watford (christopher.watford@gmail.com)
Added cast and mask to suffice size_t v. unsigned int conversion
correctness
* json_tokener.c - sign reversal issue on error info for nested object parse
spotted by Johan Björklund (johbjo09 at kth.se)
* json_object.c - escape " in json_escape_str
* Change to automake and libtool to build shared and static library
Michael Clark <michael@metaparadigm.com>
0.1
===
* initial release

2
thirdparty/json-c/INSTALL vendored Normal file
View File

@@ -0,0 +1,2 @@
See README.md for installation instructions.

1
thirdparty/json-c/NEWS vendored Normal file
View File

@@ -0,0 +1 @@
See the git repo.

1
thirdparty/json-c/README vendored Normal file
View File

@@ -0,0 +1 @@
See README.md or README.html

41
thirdparty/json-c/README.html vendored Normal file
View File

@@ -0,0 +1,41 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>JSON-C - A JSON implementation in C</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body>
<h2>JSON-C - A JSON implementation in C</h2>
<h3>Overview</h3>
<p>JSON-C implements a reference counting object model that allows you to easily
construct JSON objects in C, output them as JSON formatted strings and parse
JSON formatted strings back into the C representation of JSON objects.
It aims to conform to <a href="https://tools.ietf.org/html/rfc7159">RFC 7159</a>.
</p>
<h3>Building</h3>
<p>To setup JSON-C to build on your system please run <tt>configure</tt> and <tt>make</tt>.</p>
<p>If you are on Win32 cmake is required, generally:</p>
<ul>
<li>mkdir build</li>
<li>cd build</li>
<li>cmake ..</li>
<li>msbuild "json-c.vcxproj" /m /verbosity:normal /p:OutDir=lib\</li>
<li>Or, open the project in Visual Studio</li>
</ul>
<h3>Documentation</h3>
<P>Doxygen generated documentation exists <a href="https://json-c.github.io/json-c/">here</a>.</P>
<h3><a href="https://github.com/json-c/json-c">GIT Reposository</a></h3>
<p><strong><code>git clone https://github.com/json-c/json-c.git</code></strong></p>
<h3><a href="https://groups.google.com/group/json-c">Mailing List</a></h3>
<pi>Send email to <strong><code>json-c <i>&lt;at&gt;</i> googlegroups <i>&lt;dot&gt;</i> com</code></strong></p>
<h3><a href="COPYING">License</a></h3>
<p>This program is free software; you can redistribute it and/or modify it under the terms of the MIT License.</p>
<hr/>
</body>
</html>

345
thirdparty/json-c/README.md vendored Normal file
View File

@@ -0,0 +1,345 @@
\mainpage
`json-c`
========
1. [Overview and Build Status](#overview)
2. [Getting Help](#gettinghelp)
3. [Building on Unix](#buildunix)
* [Prerequisites](#installprereq)
* [Build commands](#buildcmds)
4. [CMake options](#CMake)
5. [Testing](#testing)
6. [Building with `vcpkg`](#buildvcpkg)
7. [Building for Android](#android)
7. [Linking to libjson-c](#linking)
8. [Using json-c](#using)
JSON-C - A JSON implementation in C <a name="overview"></a>
-----------------------------------
JSON-C implements a reference counting object model that allows you to easily
construct JSON objects in C, output them as JSON formatted strings and parse
JSON formatted strings back into the C representation of JSON objects.
It aims to conform to [RFC 7159](https://tools.ietf.org/html/rfc7159).
Skip down to [Using json-c](#using)
or check out the [API docs](https://json-c.github.io/json-c/),
if you already have json-c installed and ready to use.
Home page for json-c: https://github.com/json-c/json-c/wiki
Getting Help <a name="gettinghelp"></a>
------------
If you have questions about using json-c, please start a thread on
our forums at: https://groups.google.com/forum/#!forum/json-c
If you believe you've discovered a bug, report it at
(https://github.com/json-c/json-c/issues). Please be sure to include
the version of json-c you're using, the OS you're running on, and any
other relevant details. Fully reproducible test cases and/or patches
to fix problems are greatly appreciated.
Fixes for bugs, or small new features can be directly submitted as a
[pull request](https://github.com/json-c/json-c/pulls). For major new
features or large changes of any kind, please first start a discussion
on the [forums](https://groups.google.com/forum/#!forum/json-c).
Building on Unix with `git`, `gcc` and `cmake` <a name="buildunix"></a>
--------------------------------------------------
If you already have json-c installed, see [Linking to `libjson-c`](#linking)
for how to build and link your program against it.
Build Status
* [AppVeyor Build](https://ci.appveyor.com/project/hawicz/json-c) ![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/json-c/json-c?branch=master&svg=true)
* [Travis Build](https://app.travis-ci.com/github/json-c/json-c) ![Travis Build Status](https://api.travis-ci.com/json-c/json-c.svg?branch=master)
Test Status
* [Coveralls](https://coveralls.io/github/json-c/json-c?branch=master) [![Coverage Status](https://coveralls.io/repos/github/json-c/json-c/badge.svg?branch=master)](https://coveralls.io/github/json-c/json-c?branch=master)
### Prerequisites: <a name="installprereq"></a>
- `gcc`, `clang`, or another C compiler
- `cmake>=2.8`, `>=3.16` recommended, `cmake=>3.1` for tests
To generate docs you'll also need:
- `doxygen>=1.8.13`
If you are on a relatively modern system, you'll likely be able to install
the prerequisites using your OS's packaging system.
### Install using apt (e.g. Ubuntu 16.04.2 LTS)
```sh
sudo apt install git
sudo apt install cmake
sudo apt install doxygen # optional
sudo apt install valgrind # optional
```
### Build instructions: <a name="buildcmds"></a>
`json-c` GitHub repo: https://github.com/json-c/json-c
```sh
$ git clone https://github.com/json-c/json-c.git
$ mkdir json-c-build
$ cd json-c-build
$ cmake ../json-c # See CMake section below for custom arguments
```
Note: it's also possible to put your build directory inside the json-c
source directory, or even not use a separate build directory at all, but
certain things might not work quite right (notably, `make distcheck`)
Then:
```sh
$ make
$ make test
$ make USE_VALGRIND=0 test # optionally skip using valgrind
$ sudo make install # it could be necessary to execute make install
```
### Generating documentation with Doxygen:
The library documentation can be generated directly from the source code using Doxygen tool:
```sh
# in build directory
make doc
google-chrome doc/html/index.html
```
CMake Options <a name="CMake"></a>
--------------------
The json-c library is built with [CMake](https://cmake.org/cmake-tutorial/),
which can take a few options.
Variable | Type | Description
-----------------------------|--------|--------------
CMAKE_INSTALL_PREFIX | String | The install location.
CMAKE_BUILD_TYPE | String | Defaults to "debug".
BUILD_SHARED_LIBS | Bool | The default build generates a dynamic (dll/so) library. Set this to OFF to create a static library only.
BUILD_STATIC_LIBS | Bool | The default build generates a static (lib/a) library. Set this to OFF to create a shared library only.
DISABLE_STATIC_FPIC | Bool | The default builds position independent code. Set this to OFF to create a shared library only.
DISABLE_BSYMBOLIC | Bool | Disable use of -Bsymbolic-functions.
DISABLE_THREAD_LOCAL_STORAGE | Bool | Disable use of Thread-Local Storage (HAVE___THREAD).
DISABLE_WERROR | Bool | Disable use of -Werror.
DISABLE_EXTRA_LIBS | Bool | Disable use of extra libraries, libbsd
DISABLE_JSON_POINTER | Bool | Omit json_pointer support from the build.
ENABLE_RDRAND | Bool | Enable RDRAND Hardware RNG Hash Seed.
ENABLE_THREADING | Bool | Enable partial threading support.
OVERRIDE_GET_RANDOM_SEED | String | A block of code to use instead of the default implementation of json_c_get_random_seed(), e.g. on embedded platforms where not even the fallback to time() works. Must be a single line.
Pass these options as `-D` on CMake's command-line.
```sh
# build a static library only
cmake -DBUILD_SHARED_LIBS=OFF ..
```
### Building with partial threading support
Although json-c does not support fully multi-threaded access to
object trees, it has some code to help make its use in threaded programs
a bit safer. Currently, this is limited to using atomic operations for
json_object_get() and json_object_put().
Since this may have a performance impact, of at least 3x slower
according to https://stackoverflow.com/a/11609063, it is disabled by
default. You may turn it on by adjusting your cmake command with:
-DENABLE_THREADING=ON
Separately, the default hash function used for object field keys,
lh_char_hash, uses a compare-and-swap operation to ensure the random
seed is only generated once. Because this is a one-time operation, it
is always compiled in when the compare-and-swap operation is available.
### cmake-configure wrapper script
For those familiar with the old autoconf/autogen.sh/configure method,
there is a `cmake-configure` wrapper script to ease the transition to cmake.
```sh
mkdir build
cd build
../cmake-configure --prefix=/some/install/path
make
```
cmake-configure can take a few options.
| options | Description|
| ---- | ---- |
| prefix=PREFIX | install architecture-independent files in PREFIX |
| enable-threading | Enable code to support partly multi-threaded use |
| enable-rdrand | Enable RDRAND Hardware RNG Hash Seed generation on supported x86/x64 platforms. |
| enable-shared | build shared libraries [default=yes] |
| enable-static | build static libraries [default=yes] |
| disable-Bsymbolic | Avoid linking with -Bsymbolic-function |
| disable-werror | Avoid treating compiler warnings as fatal errors |
Testing: <a name="testing"></a>
----------
By default, if valgrind is available running tests uses it.
That can slow the tests down considerably, so to disable it use:
```sh
export USE_VALGRIND=0
```
To run tests a separate build directory is recommended:
```sh
mkdir build-test
cd build-test
# VALGRIND=1 causes -DVALGRIND=1 to be passed when compiling code
# which uses slightly slower, but valgrind-safe code.
VALGRIND=1 cmake ..
make
make test
# By default, if valgrind is available running tests uses it.
make USE_VALGRIND=0 test # optionally skip using valgrind
```
If a test fails, check `Testing/Temporary/LastTest.log`,
`tests/testSubDir/${testname}/${testname}.vg.out`, and other similar files.
If there is insufficient output try:
```sh
VERBOSE=1 CTEST_OUTPUT_ON_FAILURE=1 make test
```
or
```sh
JSONC_TEST_TRACE=1 make test
```
and check the log files again.
Building on Unix and Windows with `vcpkg` <a name="buildvcpkg"></a>
--------------------------------------------------
You can download and install JSON-C using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
vcpkg install json-c
The JSON-C port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
Building for Android <a name="android">
----------------------
Building on Android is now particularly well supported, but there
have been some reports of success using
https://developer.android.com/ndk/guides/cmake
```
mkdir json-c-build
cd json-c-build/
export NDK_HOME=~/Library/Android/sdk/ndk/22.1.7171670/
cmake \
--toolchain=$NDK_HOME/build/cmake/android.toolchain.cmake \
-DANDROID_STL=none \
-DANDROID_ABI=arm64-v8a \
-DANDROID_PLATFORM=android-29 \
-DANDROID_LD=lld \
-DCMAKE_BUILD_TYPE=MinSizeRel \
-DCMAKE_INSTALL_PREFIX=<install prefix> \
-DENABLE_THREADING=true \
..
make install
```
Linking to `libjson-c` <a name="linking">
----------------------
If your system has `pkgconfig`,
then you can just add this to your `makefile`:
```make
CFLAGS += $(shell pkg-config --cflags json-c)
LDFLAGS += $(shell pkg-config --libs json-c)
```
Without `pkgconfig`, you might do something like this:
```make
JSON_C_DIR=/path/to/json_c/install
CFLAGS += -I$(JSON_C_DIR)/include/json-c
# Or to use lines like: #include <json-c/json_object.h>
#CFLAGS += -I$(JSON_C_DIR)/include
LDFLAGS+= -L$(JSON_C_DIR)/lib -ljson-c
```
If your project uses cmake:
* Add to your CMakeLists.txt file:
```cmake
find_package(json-c CONFIG)
target_link_libraries(${PROJECT_NAME} PRIVATE json-c::json-c)
```
* Then you might run in your project:
```sh
cd build
cmake -DCMAKE_PREFIX_PATH=/path/to/json_c/install/lib64/cmake ..
```
Using json-c <a name="using">
------------
To use json-c you can either include json.h, or preferably, one of the
following more specific header files:
* json_object.h - Core types and methods.
* json_tokener.h - Methods for parsing and serializing json-c object trees.
* json_pointer.h - JSON Pointer (RFC 6901) implementation for retrieving
objects from a json-c object tree.
* json_object_iterator.h - Methods for iterating over single json_object instances. (See also `json_object_object_foreach()` in json_object.h)
* json_visit.h - Methods for walking a tree of json-c objects.
* json_util.h - Miscellaneous utility functions.
For a full list of headers see [files.html](https://json-c.github.io/json-c/json-c-current-release/doc/html/files.html)
The primary type in json-c is json_object. It describes a reference counted
tree of json objects which are created by either parsing text with a
json_tokener (i.e. `json_tokener_parse_ex()`), or by creating
(with `json_object_new_object()`, `json_object_new_int()`, etc...) and adding
(with `json_object_object_add()`, `json_object_array_add()`, etc...) them
individually.
Typically, every object in the tree will have one reference, from its parent.
When you are done with the tree of objects, you call json_object_put() on just
the root object to free it, which recurses down through any child objects
calling json_object_put() on each one of those in turn.
You can get a reference to a single child
(`json_object_object_get()` or `json_object_array_get_idx()`)
and use that object as long as its parent is valid.
If you need a child object to live longer than its parent, you can
increment the child's refcount (`json_object_get()`) to allow it to survive
the parent being freed or it being removed from its parent
(`json_object_object_del()` or `json_object_array_del_idx()`)
When parsing text, the json_tokener object is independent from the json_object
that it returns. It can be allocated (`json_tokener_new()`)
used one or multiple times (`json_tokener_parse_ex()`, and
freed (`json_tokener_free()`) while the json_object objects live on.
A json_object tree can be serialized back into a string with
`json_object_to_json_string_ext()`. The string that is returned
is only valid until the next "to_json_string" call on that same object.
Also, it is freed when the json_object is freed.

180
thirdparty/json-c/RELEASE_CHECKLIST.txt vendored Normal file
View File

@@ -0,0 +1,180 @@
# Release checklist:
## Pre-release tasks
* Figure out whether a release is worthwhile to do.
* Analyze the previous release branch to see if anything should have been
applied to master.
* Collect changes and assemble tentative release notes.
* Identify previous release branch point
* Check commit logs between previous branch point and now for
notable changes worth mentioning
* Create a new issues_closed_for_X.Y.md file
* Include notable entries from here in the release notes.
* Analyze APIs between previous release branch and master to produce list of
changes (added/removed/updated funcs, etc...), and detect backwards compat
issues.
* https://github.com/lvc/abi-compliance-checker
* If the new release is not backwards compatible, then this is a MAJOR release.
* Mention removed features in ChangeLog
* Consider re-adding backwards compatible support, through symbol
aliases and appropriate entries in json-c.sym
* Be sure any new symbols are listed in json-c.sym as part of
the _new_ release version.
* Update the AUTHORS file
PREV=$(git tag | tail -1)
( git log -r ${PREV}..HEAD | grep Author: | sed -e's/Author: //' ; cat AUTHORS ) | sort -u > A1
mv A1 AUTHORS
* Exclude mentioning changes that have already been included in a point
release of the previous release branch.
* Update ChangeLog with relevant notes before branching.
* Check that the compile works on Linux - automatic through Travis
* Check that the compile works on NetBSD
* Check that the compile works on Windows - automatic through AppVeyor
## Release creation
Start creating the new release:
release=0.16
git clone https://github.com/json-c/json-c json-c-${release}
mkdir distcheck
cd distcheck
# Note, the build directory *must* be entirely separate from
# the source tree for distcheck to work properly.
cmake -DCMAKE_BUILD_TYPE=Release ../json-c-${release}
make distcheck
cd ..
Make any fixes/changes *before* branching.
cd json-c-${release}
git branch json-c-${release}
git checkout json-c-${release}
------------
Using ${release}:
Update the version in json_c_version.h
Update the version in CMakeLists.txt (VERSION in the project(...) line)
Update the set_target_properties() line in CmakeLists.txt to set the shared
library version. Generally, unless we're doing a major release, change:
VERSION x.y.z
to
VERSION x.y+1.z
git commit -a -m "Bump version to ${release}"
If we're doing a major release (SONAME bump), also bump the version
of ALL symbols in json-c.sym.
See explanation at https://github.com/json-c/json-c/issues/621
More info at: https://software.intel.com/sites/default/files/m/a/1/e/dsohowto.pdf
------------
Generate the doxygen documentation:
(cd ../distcheck && make doc)
cp -r -p ../distcheck/doc/{html,Doxyfile} doc/.
rm doc/Doxyfile # Remove generated file w/ hardcoded paths
git add -f doc
git commit doc -m "Generate docs for the ${release} release"
------------
Create the release tarballs:
cd ..
echo .git > excludes
tar -czf json-c-${release}.tar.gz -X excludes json-c-${release}
echo 'doc/*' >> excludes
tar -czf json-c-${release}-nodoc.tar.gz -X excludes json-c-${release}
------------
Tag the branch:
cd json-c-${release}
git tag -a json-c-${release}-$(date +%Y%m%d) -m "Release json-c-${release}"
git push origin json-c-${release}
git push --tags
------------
Go to Amazon S3 service at:
https://console.aws.amazon.com/s3/
Upload the two tarballs in the json-c_releases/releases folder.
* Expand "Permissions", pick "Grant public-read access"
* Expand "Properties", ensure "Standard" storage class is picked.
Logout of Amazon S3, and verify that the files are visible.
https://s3.amazonaws.com/json-c_releases/releases/index.html
===================================
Post-release checklist:
git checkout master
Add new section to ChangeLog for ${release}+1
Use ${release}.99 to indicate a version "newer" than anything on the branch:
Update the version in json_c_version.h
Update the version in CMakeLists.txt
Update RELEASE_CHECKLIST.txt, set release=${release}+1
Add a new empty section to the json-c.sym file, for ${release}+1
Update the set_target_properties() line in CmakeLists.txt to match the release branch.
git commit -a -m "Update the master branch to version ${release}.99"
git push
------------
Update the gh-pages branch with new docs:
cd json-c-${release}
git checkout json-c-${release}
cd ..
git clone -b gh-pages https://github.com/json-c/json-c json-c-pages
cd json-c-pages
mkdir json-c-${release}
cp -R ../json-c-${release}/doc json-c-${release}/.
git add json-c-${release}
rm json-c-current-release
ln -s json-c-${release} json-c-current-release
git commit -a -m "Add the ${release} docs."
vi index.html
# Add/change links to current release.
git commit -a -m "Update the doc links to point at ${release}"
git push
------------
Update checksums on wiki page.
cd ..
openssl sha -sha256 json-c*gz
openssl md5 json-c*gz
Copy and paste this output into the wiki page at:
https://github.com/json-c/json-c/wiki
------------
Send an email to the mailing list.

Some files were not shown because too many files have changed in this diff Show More