mirror of
https://github.com/SChernykh/p2pool.git
synced 2024-11-16 15:57:39 +00:00
commit
0c4dc82c65
33 changed files with 647 additions and 16410 deletions
131
.github/workflows/c-cpp.yml
vendored
131
.github/workflows/c-cpp.yml
vendored
|
@ -1,10 +1,6 @@
|
||||||
name: C/C++ CI
|
name: C/C++ CI
|
||||||
|
|
||||||
on:
|
on: [push, pull_request]
|
||||||
push:
|
|
||||||
branches: [ master ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ master ]
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-ubuntu:
|
build-ubuntu:
|
||||||
|
@ -22,7 +18,7 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install -y git build-essential cmake libuv1-dev libzmq3-dev libsodium-dev libpgm-dev libnorm-dev libgss-dev ${{ matrix.config.c }} ${{ matrix.config.cpp }}
|
sudo apt install -y git build-essential cmake libuv1-dev libzmq3-dev libsodium-dev libpgm-dev libnorm-dev libgss-dev libcurl4-openssl-dev libidn2-0-dev ${{ matrix.config.c }} ${{ matrix.config.cpp }}
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
@ -34,7 +30,7 @@ jobs:
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake .. -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_CXX_COMPILER=${{ matrix.config.cpp }}
|
cmake .. -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_CXX_COMPILER=${{ matrix.config.cpp }}
|
||||||
make -j2
|
make -j$(nproc)
|
||||||
|
|
||||||
- name: Build tests
|
- name: Build tests
|
||||||
run: |
|
run: |
|
||||||
|
@ -42,7 +38,7 @@ jobs:
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake .. -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_CXX_COMPILER=${{ matrix.config.cpp }}
|
cmake .. -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_CXX_COMPILER=${{ matrix.config.cpp }}
|
||||||
make -j2
|
make -j$(nproc)
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: cd tests/build && ./p2pool_tests
|
run: cd tests/build && ./p2pool_tests
|
||||||
|
@ -53,6 +49,68 @@ jobs:
|
||||||
name: p2pool-${{ matrix.config.os }}
|
name: p2pool-${{ matrix.config.os }}
|
||||||
path: build/p2pool
|
path: build/p2pool
|
||||||
|
|
||||||
|
build-ubuntu-static-libs:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y git build-essential cmake autoconf libgss-dev
|
||||||
|
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
|
||||||
|
- name: Build libcurl
|
||||||
|
run: |
|
||||||
|
cd external/src/curl
|
||||||
|
autoreconf -fi
|
||||||
|
./configure --without-ssl --without-hyper --without-zlib --without-brotli --without-zstd --without-default-ssl-backend --without-ca-bundle --without-ca-path --without-ca-fallback --without-libpsl --without-libgsasl --without-librtmp --without-winidn --without-libidn2 --without-nghttp2 --without-ngtcp2 --without-nghttp3 --without-quiche --without-msh3 --without-zsh-functions-dir --without-fish-functions-dir --disable-ftp --disable-file --disable-ldap --disable-ldaps --disable-rtsp --disable-proxy --disable-dict --disable-telnet --disable-tftp --disable-pop3 --disable-imap --disable-smb --disable-smtp --disable-gopher --disable-mqtt --disable-manual --disable-ntlm --disable-ntlm-wb --disable-tls-srp --disable-unix-sockets --disable-cookies --disable-socketpair --disable-doh --disable-dateparse --disable-netrc --disable-progress-meter --disable-dnsshuffle --disable-hsts
|
||||||
|
make -j$(nproc)
|
||||||
|
|
||||||
|
- name: Build libuv
|
||||||
|
run: |
|
||||||
|
cd external/src/libuv
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake .. -DBUILD_TESTING=OFF
|
||||||
|
make -j$(nproc)
|
||||||
|
|
||||||
|
- name: Build libzmq
|
||||||
|
run: |
|
||||||
|
cd external/src/libzmq
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake .. -DWITH_TLS=OFF -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF
|
||||||
|
make -j$(nproc)
|
||||||
|
|
||||||
|
- name: Build p2pool
|
||||||
|
run: |
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake .. -DSTATIC_LIBS=ON
|
||||||
|
make -j$(nproc)
|
||||||
|
|
||||||
|
- name: Build tests
|
||||||
|
run: |
|
||||||
|
cd tests
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake .. -DSTATIC_LIBS=ON
|
||||||
|
make -j$(nproc)
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: cd tests/build && ./p2pool_tests
|
||||||
|
|
||||||
|
- name: Archive binary
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: p2pool-ubuntu-static-libs
|
||||||
|
path: build/p2pool
|
||||||
|
|
||||||
build-ubuntu-aarch64:
|
build-ubuntu-aarch64:
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
@ -61,19 +119,26 @@ jobs:
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install -y git build-essential cmake gcc-aarch64-linux-gnu g++-aarch64-linux-gnu binutils-aarch64-linux-gnu
|
sudo apt install -y git build-essential cmake autoconf gcc-aarch64-linux-gnu g++-aarch64-linux-gnu binutils-aarch64-linux-gnu
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
|
||||||
|
- name: Build libcurl
|
||||||
|
run: |
|
||||||
|
cd external/src/curl
|
||||||
|
autoreconf -fi
|
||||||
|
./configure --host=aarch64-linux-gnu --without-ssl --without-hyper --without-zlib --without-brotli --without-zstd --without-default-ssl-backend --without-ca-bundle --without-ca-path --without-ca-fallback --without-libpsl --without-libgsasl --without-librtmp --without-winidn --without-libidn2 --without-nghttp2 --without-ngtcp2 --without-nghttp3 --without-quiche --without-msh3 --without-zsh-functions-dir --without-fish-functions-dir --disable-ftp --disable-file --disable-ldap --disable-ldaps --disable-rtsp --disable-proxy --disable-dict --disable-telnet --disable-tftp --disable-pop3 --disable-imap --disable-smb --disable-smtp --disable-gopher --disable-mqtt --disable-manual --disable-ntlm --disable-ntlm-wb --disable-tls-srp --disable-unix-sockets --disable-cookies --disable-socketpair --disable-doh --disable-dateparse --disable-netrc --disable-progress-meter --disable-dnsshuffle --disable-hsts
|
||||||
|
make -j$(nproc)
|
||||||
|
|
||||||
- name: Build libuv
|
- name: Build libuv
|
||||||
run: |
|
run: |
|
||||||
cd external/src/libuv
|
cd external/src/libuv
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake .. -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++
|
cmake .. -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ -DBUILD_TESTING=OFF
|
||||||
make -j$(nproc)
|
make -j$(nproc)
|
||||||
|
|
||||||
- name: Build libzmq
|
- name: Build libzmq
|
||||||
|
@ -115,22 +180,45 @@ jobs:
|
||||||
uses: eine/setup-msys2@v2
|
uses: eine/setup-msys2@v2
|
||||||
with:
|
with:
|
||||||
update: true
|
update: true
|
||||||
install: mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-libuv
|
install: mingw-w64-x86_64-toolchain mingw-w64-x86_64-cmake make autoconf libtool automake
|
||||||
|
|
||||||
|
- name: Build libcurl
|
||||||
|
run: |
|
||||||
|
cd external/src/curl
|
||||||
|
autoreconf -fi
|
||||||
|
./configure --without-ssl --without-hyper --without-zlib --without-brotli --without-zstd --without-default-ssl-backend --without-ca-bundle --without-ca-path --without-ca-fallback --without-libpsl --without-libgsasl --without-librtmp --without-winidn --without-libidn2 --without-nghttp2 --without-ngtcp2 --without-nghttp3 --without-quiche --without-msh3 --without-zsh-functions-dir --without-fish-functions-dir --disable-ftp --disable-file --disable-ldap --disable-ldaps --disable-rtsp --disable-proxy --disable-dict --disable-telnet --disable-tftp --disable-pop3 --disable-imap --disable-smb --disable-smtp --disable-gopher --disable-mqtt --disable-manual --disable-ntlm --disable-ntlm-wb --disable-tls-srp --disable-unix-sockets --disable-cookies --disable-socketpair --disable-doh --disable-dateparse --disable-netrc --disable-progress-meter --disable-dnsshuffle --disable-hsts
|
||||||
|
make -j$(nproc)
|
||||||
|
|
||||||
|
- name: Build libuv
|
||||||
|
run: |
|
||||||
|
cd external/src/libuv
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake .. -G "Unix Makefiles" -DBUILD_TESTING=OFF
|
||||||
|
make -j$(nproc)
|
||||||
|
|
||||||
|
- name: Build libzmq
|
||||||
|
run: |
|
||||||
|
cd external/src/libzmq
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake .. -G "Unix Makefiles" -DWITH_TLS=OFF -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DZMQ_HAVE_IPC=OFF
|
||||||
|
make -j$(nproc)
|
||||||
|
|
||||||
- name: Build p2pool
|
- name: Build p2pool
|
||||||
run: |
|
run: |
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake .. -G "Unix Makefiles"
|
cmake .. -G "Unix Makefiles" -DSTATIC_LIBS=ON
|
||||||
make -j2
|
make -j$(nproc)
|
||||||
|
|
||||||
- name: Build tests
|
- name: Build tests
|
||||||
run: |
|
run: |
|
||||||
cd tests
|
cd tests
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake .. -G "Unix Makefiles"
|
cmake .. -G "Unix Makefiles" -DSTATIC_LIBS=ON
|
||||||
make -j2
|
make -j$(nproc)
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: |
|
run: |
|
||||||
|
@ -204,14 +292,21 @@ jobs:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install cmake
|
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install cmake autoconf libtool automake
|
||||||
|
|
||||||
|
- name: Build libcurl
|
||||||
|
run: |
|
||||||
|
cd external/src/curl
|
||||||
|
autoreconf -fi
|
||||||
|
./configure --without-ssl --without-hyper --without-zlib --without-brotli --without-zstd --without-default-ssl-backend --without-ca-bundle --without-ca-path --without-ca-fallback --without-libpsl --without-libgsasl --without-librtmp --without-winidn --without-libidn2 --without-nghttp2 --without-ngtcp2 --without-nghttp3 --without-quiche --without-msh3 --without-zsh-functions-dir --without-fish-functions-dir --disable-ftp --disable-file --disable-ldap --disable-ldaps --disable-rtsp --disable-proxy --disable-dict --disable-telnet --disable-tftp --disable-pop3 --disable-imap --disable-smb --disable-smtp --disable-gopher --disable-mqtt --disable-manual --disable-ntlm --disable-ntlm-wb --disable-tls-srp --disable-unix-sockets --disable-cookies --disable-socketpair --disable-doh --disable-dateparse --disable-netrc --disable-progress-meter --disable-dnsshuffle --disable-hsts
|
||||||
|
make -j3
|
||||||
|
|
||||||
- name: Build libuv
|
- name: Build libuv
|
||||||
run: |
|
run: |
|
||||||
cd external/src/libuv
|
cd external/src/libuv
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake ..
|
cmake .. -DBUILD_TESTING=OFF
|
||||||
make -j3
|
make -j3
|
||||||
|
|
||||||
- name: Build libzmq
|
- name: Build libzmq
|
||||||
|
@ -219,7 +314,7 @@ jobs:
|
||||||
cd external/src/libzmq
|
cd external/src/libzmq
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake .. -DWITH_TLS=OFF -DWITH_LIBSODIUM=OFF
|
cmake .. -DWITH_TLS=OFF -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF
|
||||||
make -j3
|
make -j3
|
||||||
|
|
||||||
- name: Build p2pool
|
- name: Build p2pool
|
||||||
|
|
5
.github/workflows/codeql-analysis.yml
vendored
5
.github/workflows/codeql-analysis.yml
vendored
|
@ -13,10 +13,7 @@ name: "CodeQL"
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ master ]
|
|
||||||
pull_request:
|
pull_request:
|
||||||
# The branches below must be a subset of the branches above
|
|
||||||
branches: [ master ]
|
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '44 11 * * 0'
|
- cron: '44 11 * * 0'
|
||||||
|
|
||||||
|
@ -40,7 +37,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt update && sudo apt install git build-essential cmake libuv1-dev libzmq3-dev libsodium-dev libpgm-dev libnorm-dev libgss-dev
|
sudo apt update && sudo apt install git build-essential cmake libuv1-dev libzmq3-dev libsodium-dev libpgm-dev libnorm-dev libgss-dev libcurl4-openssl-dev libidn2-0-dev
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
6
.github/workflows/cppcheck.yml
vendored
6
.github/workflows/cppcheck.yml
vendored
|
@ -1,10 +1,6 @@
|
||||||
name: cppcheck
|
name: cppcheck
|
||||||
|
|
||||||
on:
|
on: [push, pull_request]
|
||||||
push:
|
|
||||||
branches: [ master ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ master ]
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
cppcheck-ubuntu:
|
cppcheck-ubuntu:
|
||||||
|
|
2
.github/workflows/msvc-analysis.yml
vendored
2
.github/workflows/msvc-analysis.yml
vendored
|
@ -10,9 +10,7 @@ name: Microsoft C++ Code Analysis
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ master ]
|
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ master ]
|
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '40 10 * * 0'
|
- cron: '40 10 * * 0'
|
||||||
|
|
||||||
|
|
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -19,3 +19,6 @@
|
||||||
[submodule "external/src/robin-hood-hashing"]
|
[submodule "external/src/robin-hood-hashing"]
|
||||||
path = external/src/robin-hood-hashing
|
path = external/src/robin-hood-hashing
|
||||||
url = https://github.com/SChernykh/robin-hood-hashing
|
url = https://github.com/SChernykh/robin-hood-hashing
|
||||||
|
[submodule "external/src/curl"]
|
||||||
|
path = external/src/curl
|
||||||
|
url = https://github.com/SChernykh/curl
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
cmake_minimum_required(VERSION 2.8.12)
|
cmake_minimum_required(VERSION 3.12)
|
||||||
project(p2pool)
|
project(p2pool)
|
||||||
|
|
||||||
option(STATIC_BINARY "Build static binary" OFF)
|
option(STATIC_BINARY "Build static binary" OFF)
|
||||||
|
@ -7,9 +7,7 @@ option(WITH_RANDOMX "Include the RandomX library in the build. If this is turned
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.6.0")
|
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT p2pool)
|
||||||
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT p2pool)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (WITH_RANDOMX)
|
if (WITH_RANDOMX)
|
||||||
add_definitions(-DWITH_RANDOMX)
|
add_definitions(-DWITH_RANDOMX)
|
||||||
|
@ -21,7 +19,6 @@ include(cmake/flags.cmake)
|
||||||
|
|
||||||
set(HEADERS
|
set(HEADERS
|
||||||
external/src/cryptonote/crypto-ops.h
|
external/src/cryptonote/crypto-ops.h
|
||||||
external/src/llhttp/llhttp.h
|
|
||||||
src/block_cache.h
|
src/block_cache.h
|
||||||
src/block_template.h
|
src/block_template.h
|
||||||
src/common.h
|
src/common.h
|
||||||
|
@ -52,9 +49,6 @@ set(HEADERS
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
external/src/cryptonote/crypto-ops-data.c
|
external/src/cryptonote/crypto-ops-data.c
|
||||||
external/src/cryptonote/crypto-ops.c
|
external/src/cryptonote/crypto-ops.c
|
||||||
external/src/llhttp/api.c
|
|
||||||
external/src/llhttp/http.c
|
|
||||||
external/src/llhttp/llhttp.c
|
|
||||||
src/block_cache.cpp
|
src/block_cache.cpp
|
||||||
src/block_template.cpp
|
src/block_template.cpp
|
||||||
src/console_commands.cpp
|
src/console_commands.cpp
|
||||||
|
@ -86,10 +80,10 @@ endif()
|
||||||
include_directories(src)
|
include_directories(src)
|
||||||
include_directories(external/src)
|
include_directories(external/src)
|
||||||
include_directories(external/src/cryptonote)
|
include_directories(external/src/cryptonote)
|
||||||
|
include_directories(external/src/curl/include)
|
||||||
include_directories(external/src/libuv/include)
|
include_directories(external/src/libuv/include)
|
||||||
include_directories(external/src/cppzmq)
|
include_directories(external/src/cppzmq)
|
||||||
include_directories(external/src/libzmq/include)
|
include_directories(external/src/libzmq/include)
|
||||||
include_directories(external/src/llhttp)
|
|
||||||
if (WITH_RANDOMX)
|
if (WITH_RANDOMX)
|
||||||
include_directories(external/src/RandomX/src)
|
include_directories(external/src/RandomX/src)
|
||||||
endif()
|
endif()
|
||||||
|
@ -98,6 +92,7 @@ include_directories(external/src/robin-hood-hashing/src/include)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
set(LIBS ${LIBS} ws2_32 iphlpapi userenv psapi)
|
set(LIBS ${LIBS} ws2_32 iphlpapi userenv psapi)
|
||||||
|
add_definitions(-DCURL_STATICLIB)
|
||||||
elseif (CMAKE_SYSTEM_NAME STREQUAL FreeBSD)
|
elseif (CMAKE_SYSTEM_NAME STREQUAL FreeBSD)
|
||||||
set(LIBS ${LIBS} pthread)
|
set(LIBS ${LIBS} pthread)
|
||||||
elseif (NOT APPLE)
|
elseif (NOT APPLE)
|
||||||
|
@ -109,11 +104,20 @@ if (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||||
find_library(ZMQ_LIBRARY NAMES libzmq-v142-mt-s-4_3_5 PATHS "external/lib/libzmq/Release")
|
find_library(ZMQ_LIBRARY NAMES libzmq-v142-mt-s-4_3_5 PATHS "external/lib/libzmq/Release")
|
||||||
find_library(UV_LIBRARY_DEBUG NAMES uv_a PATHS "external/lib/libuv/Debug")
|
find_library(UV_LIBRARY_DEBUG NAMES uv_a PATHS "external/lib/libuv/Debug")
|
||||||
find_library(UV_LIBRARY NAMES uv_a PATHS "external/lib/libuv/Release")
|
find_library(UV_LIBRARY NAMES uv_a PATHS "external/lib/libuv/Release")
|
||||||
|
find_library(CURL_LIBRARY_DEBUG NAMES libcurld PATHS "external/lib/libcurl/Debug")
|
||||||
|
find_library(CURL_LIBRARY NAMES libcurl PATHS "external/lib/libcurl/Release")
|
||||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES GNU OR CMAKE_CXX_COMPILER_ID MATCHES Clang)
|
elseif (CMAKE_CXX_COMPILER_ID MATCHES GNU OR CMAKE_CXX_COMPILER_ID MATCHES Clang)
|
||||||
find_library(ZMQ_LIBRARY_DEBUG NAMES zmq libzmq.a)
|
find_library(ZMQ_LIBRARY_DEBUG NAMES zmq libzmq.a)
|
||||||
find_library(ZMQ_LIBRARY NAMES zmq libzmq.a)
|
find_library(ZMQ_LIBRARY NAMES zmq libzmq.a)
|
||||||
find_library(UV_LIBRARY_DEBUG NAMES uv libuv.a)
|
find_library(UV_LIBRARY_DEBUG NAMES uv libuv.a)
|
||||||
find_library(UV_LIBRARY NAMES uv libuv.a)
|
find_library(UV_LIBRARY NAMES uv libuv.a)
|
||||||
|
if (WIN32)
|
||||||
|
find_library(CURL_LIBRARY_DEBUG NAMES libcurl.a PATHS "external/src/curl/lib/.libs" NO_DEFAULT_PATH)
|
||||||
|
find_library(CURL_LIBRARY NAMES libcurl.a PATHS "external/src/curl/lib/.libs" NO_DEFAULT_PATH)
|
||||||
|
else()
|
||||||
|
find_library(CURL_LIBRARY_DEBUG NAMES curl)
|
||||||
|
find_library(CURL_LIBRARY NAMES curl)
|
||||||
|
endif()
|
||||||
find_library(SODIUM_LIBRARY sodium)
|
find_library(SODIUM_LIBRARY sodium)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -132,6 +136,13 @@ if (SODIUM_LIBRARY)
|
||||||
set(LIBS ${LIBS} ${SODIUM_LIBRARY})
|
set(LIBS ${LIBS} ${SODIUM_LIBRARY})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(APPLE)
|
||||||
|
find_library(FOUNDATION_LIB Foundation)
|
||||||
|
find_library(CORE_FOUNDATION_LIB CoreFoundation)
|
||||||
|
find_library(SYSTEM_CONFIGURATION_LIB SystemConfiguration)
|
||||||
|
set(LIBS ${LIBS} ${FOUNDATION_LIB} ${CORE_FOUNDATION_LIB} ${SYSTEM_CONFIGURATION_LIB})
|
||||||
|
endif()
|
||||||
|
|
||||||
add_definitions(/DZMQ_STATIC)
|
add_definitions(/DZMQ_STATIC)
|
||||||
|
|
||||||
include(CheckSymbolExists)
|
include(CheckSymbolExists)
|
||||||
|
@ -159,23 +170,35 @@ endif()
|
||||||
add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES})
|
add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES})
|
||||||
|
|
||||||
if (STATIC_BINARY OR STATIC_LIBS)
|
if (STATIC_BINARY OR STATIC_LIBS)
|
||||||
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_STRIP} ${CMAKE_PROJECT_NAME})
|
if (WIN32)
|
||||||
|
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_STRIP} "${CMAKE_PROJECT_NAME}.exe")
|
||||||
|
else()
|
||||||
|
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_STRIP} ${CMAKE_PROJECT_NAME})
|
||||||
|
endif()
|
||||||
|
|
||||||
if (WITH_RANDOMX)
|
if (WITH_RANDOMX)
|
||||||
set(STATIC_LIBS randomx)
|
set(STATIC_LIBS randomx)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL FreeBSD)
|
if (WIN32)
|
||||||
|
set(STATIC_LIBS ${STATIC_LIBS} ws2_32 iphlpapi userenv psapi wldap32)
|
||||||
|
elseif (CMAKE_SYSTEM_NAME STREQUAL FreeBSD)
|
||||||
set(STATIC_LIBS ${STATIC_LIBS} pthread)
|
set(STATIC_LIBS ${STATIC_LIBS} pthread)
|
||||||
elseif (NOT APPLE)
|
elseif (APPLE)
|
||||||
|
find_library(FOUNDATION_LIB Foundation)
|
||||||
|
find_library(CORE_FOUNDATION_LIB CoreFoundation)
|
||||||
|
find_library(SYSTEM_CONFIGURATION_LIB SystemConfiguration)
|
||||||
|
set(STATIC_LIBS ${STATIC_LIBS} ${FOUNDATION_LIB} ${CORE_FOUNDATION_LIB} ${SYSTEM_CONFIGURATION_LIB})
|
||||||
|
else()
|
||||||
set(STATIC_LIBS ${STATIC_LIBS} pthread dl)
|
set(STATIC_LIBS ${STATIC_LIBS} pthread dl)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(${CMAKE_PROJECT_NAME}
|
target_link_libraries(${CMAKE_PROJECT_NAME}
|
||||||
"${CMAKE_SOURCE_DIR}/external/src/libzmq/build/lib/libzmq.a"
|
"${CMAKE_SOURCE_DIR}/external/src/libzmq/build/lib/libzmq.a"
|
||||||
"${CMAKE_SOURCE_DIR}/external/src/libuv/build/libuv_a.a"
|
"${CMAKE_SOURCE_DIR}/external/src/libuv/build/libuv_a.a"
|
||||||
|
"${CMAKE_SOURCE_DIR}/external/src/curl/lib/.libs/libcurl.a"
|
||||||
${STATIC_LIBS}
|
${STATIC_LIBS}
|
||||||
)
|
)
|
||||||
else()
|
else()
|
||||||
target_link_libraries(${CMAKE_PROJECT_NAME} debug ${ZMQ_LIBRARY_DEBUG} debug ${UV_LIBRARY_DEBUG} optimized ${ZMQ_LIBRARY} optimized ${UV_LIBRARY} ${LIBS})
|
target_link_libraries(${CMAKE_PROJECT_NAME} debug ${ZMQ_LIBRARY_DEBUG} debug ${UV_LIBRARY_DEBUG} debug ${CURL_LIBRARY_DEBUG} optimized ${ZMQ_LIBRARY} optimized ${UV_LIBRARY} optimized ${CURL_LIBRARY} ${LIBS})
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -200,7 +200,7 @@ Please see the relevant instructions for your platform:
|
||||||
|
|
||||||
Run the following commands to install the necessary prerequisites, clone this repo, and build P2Pool locally on Ubuntu 20.04:
|
Run the following commands to install the necessary prerequisites, clone this repo, and build P2Pool locally on Ubuntu 20.04:
|
||||||
```
|
```
|
||||||
sudo apt update && sudo apt install git build-essential cmake libuv1-dev libzmq3-dev libsodium-dev libpgm-dev libnorm-dev libgss-dev
|
sudo apt update && sudo apt install git build-essential cmake libuv1-dev libzmq3-dev libsodium-dev libpgm-dev libnorm-dev libgss-dev libcurl4-openssl-dev libidn2-0-dev
|
||||||
git clone --recursive https://github.com/SChernykh/p2pool
|
git clone --recursive https://github.com/SChernykh/p2pool
|
||||||
cd p2pool
|
cd p2pool
|
||||||
mkdir build && cd build
|
mkdir build && cd build
|
||||||
|
|
|
@ -39,7 +39,6 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||||
|
|
||||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${GENERAL_FLAGS} ${WARNING_FLAGS} ${SECURITY_FLAGS} /Ob1 /Ot /Zi /MT")
|
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${GENERAL_FLAGS} ${WARNING_FLAGS} ${SECURITY_FLAGS} /Ob1 /Ot /Zi /MT")
|
||||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${GENERAL_FLAGS} ${WARNING_FLAGS} ${SECURITY_FLAGS} /Ob1 /Ot /Zi /MT")
|
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${GENERAL_FLAGS} ${WARNING_FLAGS} ${SECURITY_FLAGS} /Ob1 /Ot /Zi /MT")
|
||||||
|
|
||||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
|
elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
|
||||||
set(GENERAL_FLAGS "-pthread")
|
set(GENERAL_FLAGS "-pthread")
|
||||||
set(WARNING_FLAGS "-Wall -Wextra -Wno-undefined-internal -Wunreachable-code-aggressive -Wmissing-prototypes -Wmissing-variable-declarations -Werror")
|
set(WARNING_FLAGS "-Wall -Wextra -Wno-undefined-internal -Wunreachable-code-aggressive -Wmissing-prototypes -Wmissing-variable-declarations -Werror")
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
../external/src/libuv/include/
|
../external/src/libuv/include/
|
||||||
../external/src/cppzmq/
|
../external/src/cppzmq/
|
||||||
../external/src/libzmq/include/
|
../external/src/libzmq/include/
|
||||||
../external/src/llhttp/
|
../external/src/curl/include
|
||||||
../external/src/RandomX/src/
|
../external/src/RandomX/src/
|
||||||
../external/src/rapidjson/include
|
../external/src/rapidjson/include
|
||||||
../external/src/robin-hood-hashing/src/include
|
../external/src/robin-hood-hashing/src/include
|
||||||
|
|
BIN
external/lib/libcurl/Debug/libcurld.lib
vendored
Normal file
BIN
external/lib/libcurl/Debug/libcurld.lib
vendored
Normal file
Binary file not shown.
BIN
external/lib/libcurl/Debug/libcurld.pdb
vendored
Normal file
BIN
external/lib/libcurl/Debug/libcurld.pdb
vendored
Normal file
Binary file not shown.
BIN
external/lib/libcurl/Release/libcurl.lib
vendored
Normal file
BIN
external/lib/libcurl/Release/libcurl.lib
vendored
Normal file
Binary file not shown.
1
external/src/curl
vendored
Submodule
1
external/src/curl
vendored
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 2bd75e5686b2e6ff3824c4dfb2b6ec86b60f454c
|
22
external/src/llhttp/LICENSE-MIT
vendored
22
external/src/llhttp/LICENSE-MIT
vendored
|
@ -1,22 +0,0 @@
|
||||||
This software is licensed under the MIT License.
|
|
||||||
|
|
||||||
Copyright Fedor Indutny, 2018.
|
|
||||||
|
|
||||||
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.
|
|
379
external/src/llhttp/api.c
vendored
379
external/src/llhttp/api.c
vendored
|
@ -1,379 +0,0 @@
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning(disable : 4100 4668 4710 4711 4820)
|
|
||||||
#elif defined __clang__
|
|
||||||
#pragma clang diagnostic ignored "-Wunused-parameter"
|
|
||||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
|
||||||
#elif defined __GNUC__
|
|
||||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
|
||||||
#pragma GCC diagnostic ignored "-Wcast-qual"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "llhttp.h"
|
|
||||||
|
|
||||||
#define CALLBACK_MAYBE(PARSER, NAME) \
|
|
||||||
do { \
|
|
||||||
const llhttp_settings_t* settings; \
|
|
||||||
settings = (const llhttp_settings_t*) (PARSER)->settings; \
|
|
||||||
if (settings == NULL || settings->NAME == NULL) { \
|
|
||||||
err = 0; \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
err = settings->NAME((PARSER)); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define SPAN_CALLBACK_MAYBE(PARSER, NAME, START, LEN) \
|
|
||||||
do { \
|
|
||||||
const llhttp_settings_t* settings; \
|
|
||||||
settings = (const llhttp_settings_t*) (PARSER)->settings; \
|
|
||||||
if (settings == NULL || settings->NAME == NULL) { \
|
|
||||||
err = 0; \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
err = settings->NAME((PARSER), (START), (LEN)); \
|
|
||||||
if (err == -1) { \
|
|
||||||
err = HPE_USER; \
|
|
||||||
llhttp_set_error_reason((PARSER), "Span callback error in " #NAME); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
void llhttp_init(llhttp_t* parser, llhttp_type_t type,
|
|
||||||
const llhttp_settings_t* settings) {
|
|
||||||
llhttp__internal_init(parser);
|
|
||||||
|
|
||||||
parser->type = type;
|
|
||||||
parser->settings = (void*) settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(__wasm__)
|
|
||||||
|
|
||||||
extern int wasm_on_message_begin(llhttp_t * p);
|
|
||||||
extern int wasm_on_url(llhttp_t* p, const char* at, size_t length);
|
|
||||||
extern int wasm_on_status(llhttp_t* p, const char* at, size_t length);
|
|
||||||
extern int wasm_on_header_field(llhttp_t* p, const char* at, size_t length);
|
|
||||||
extern int wasm_on_header_value(llhttp_t* p, const char* at, size_t length);
|
|
||||||
extern int wasm_on_headers_complete(llhttp_t * p, int status_code,
|
|
||||||
uint8_t upgrade, int should_keep_alive);
|
|
||||||
extern int wasm_on_body(llhttp_t* p, const char* at, size_t length);
|
|
||||||
extern int wasm_on_message_complete(llhttp_t * p);
|
|
||||||
|
|
||||||
static int wasm_on_headers_complete_wrap(llhttp_t* p) {
|
|
||||||
return wasm_on_headers_complete(p, p->status_code, p->upgrade,
|
|
||||||
llhttp_should_keep_alive(p));
|
|
||||||
}
|
|
||||||
|
|
||||||
const llhttp_settings_t wasm_settings = {
|
|
||||||
wasm_on_message_begin,
|
|
||||||
wasm_on_url,
|
|
||||||
wasm_on_status,
|
|
||||||
wasm_on_header_field,
|
|
||||||
wasm_on_header_value,
|
|
||||||
wasm_on_headers_complete_wrap,
|
|
||||||
wasm_on_body,
|
|
||||||
wasm_on_message_complete,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
llhttp_t* llhttp_alloc(llhttp_type_t type) {
|
|
||||||
llhttp_t* parser = malloc(sizeof(llhttp_t));
|
|
||||||
llhttp_init(parser, type, &wasm_settings);
|
|
||||||
return parser;
|
|
||||||
}
|
|
||||||
|
|
||||||
void llhttp_free(llhttp_t* parser) {
|
|
||||||
free(parser);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Some getters required to get stuff from the parser */
|
|
||||||
|
|
||||||
uint8_t llhttp_get_type(llhttp_t* parser) {
|
|
||||||
return parser->type;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t llhttp_get_http_major(llhttp_t* parser) {
|
|
||||||
return parser->http_major;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t llhttp_get_http_minor(llhttp_t* parser) {
|
|
||||||
return parser->http_minor;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t llhttp_get_method(llhttp_t* parser) {
|
|
||||||
return parser->method;
|
|
||||||
}
|
|
||||||
|
|
||||||
int llhttp_get_status_code(llhttp_t* parser) {
|
|
||||||
return parser->status_code;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t llhttp_get_upgrade(llhttp_t* parser) {
|
|
||||||
return parser->upgrade;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // defined(__wasm__)
|
|
||||||
|
|
||||||
|
|
||||||
void llhttp_reset(llhttp_t* parser) {
|
|
||||||
llhttp_type_t type = parser->type;
|
|
||||||
const llhttp_settings_t* settings = parser->settings;
|
|
||||||
void* data = parser->data;
|
|
||||||
uint8_t lenient_flags = parser->lenient_flags;
|
|
||||||
|
|
||||||
llhttp__internal_init(parser);
|
|
||||||
|
|
||||||
parser->type = type;
|
|
||||||
parser->settings = (void*) settings;
|
|
||||||
parser->data = data;
|
|
||||||
parser->lenient_flags = lenient_flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len) {
|
|
||||||
return llhttp__internal_execute(parser, data, data + len);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void llhttp_settings_init(llhttp_settings_t* settings) {
|
|
||||||
memset(settings, 0, sizeof(*settings));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
llhttp_errno_t llhttp_finish(llhttp_t* parser) {
|
|
||||||
int err;
|
|
||||||
|
|
||||||
/* We're in an error state. Don't bother doing anything. */
|
|
||||||
if (parser->error != 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (parser->finish) {
|
|
||||||
case HTTP_FINISH_SAFE_WITH_CB:
|
|
||||||
CALLBACK_MAYBE(parser, on_message_complete);
|
|
||||||
if (err != HPE_OK) return err;
|
|
||||||
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case HTTP_FINISH_SAFE:
|
|
||||||
return HPE_OK;
|
|
||||||
case HTTP_FINISH_UNSAFE:
|
|
||||||
parser->reason = "Invalid EOF state";
|
|
||||||
return HPE_INVALID_EOF_STATE;
|
|
||||||
default:
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void llhttp_pause(llhttp_t* parser) {
|
|
||||||
if (parser->error != HPE_OK) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
parser->error = HPE_PAUSED;
|
|
||||||
parser->reason = "Paused";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void llhttp_resume(llhttp_t* parser) {
|
|
||||||
if (parser->error != HPE_PAUSED) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
parser->error = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void llhttp_resume_after_upgrade(llhttp_t* parser) {
|
|
||||||
if (parser->error != HPE_PAUSED_UPGRADE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
parser->error = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
llhttp_errno_t llhttp_get_errno(const llhttp_t* parser) {
|
|
||||||
return parser->error;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char* llhttp_get_error_reason(const llhttp_t* parser) {
|
|
||||||
return parser->reason;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void llhttp_set_error_reason(llhttp_t* parser, const char* reason) {
|
|
||||||
parser->reason = reason;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char* llhttp_get_error_pos(const llhttp_t* parser) {
|
|
||||||
return parser->error_pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char* llhttp_errno_name(llhttp_errno_t err) {
|
|
||||||
#define HTTP_ERRNO_GEN(CODE, NAME, _) case HPE_##NAME: return "HPE_" #NAME;
|
|
||||||
switch (err) {
|
|
||||||
HTTP_ERRNO_MAP(HTTP_ERRNO_GEN)
|
|
||||||
default: abort();
|
|
||||||
}
|
|
||||||
#undef HTTP_ERRNO_GEN
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char* llhttp_method_name(llhttp_method_t method) {
|
|
||||||
#define HTTP_METHOD_GEN(NUM, NAME, STRING) case HTTP_##NAME: return #STRING;
|
|
||||||
switch (method) {
|
|
||||||
HTTP_ALL_METHOD_MAP(HTTP_METHOD_GEN)
|
|
||||||
default: abort();
|
|
||||||
}
|
|
||||||
#undef HTTP_METHOD_GEN
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void llhttp_set_lenient_headers(llhttp_t* parser, int enabled) {
|
|
||||||
if (enabled) {
|
|
||||||
parser->lenient_flags |= LENIENT_HEADERS;
|
|
||||||
} else {
|
|
||||||
parser->lenient_flags &= ~LENIENT_HEADERS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled) {
|
|
||||||
if (enabled) {
|
|
||||||
parser->lenient_flags |= LENIENT_CHUNKED_LENGTH;
|
|
||||||
} else {
|
|
||||||
parser->lenient_flags &= ~LENIENT_CHUNKED_LENGTH;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled) {
|
|
||||||
if (enabled) {
|
|
||||||
parser->lenient_flags |= LENIENT_KEEP_ALIVE;
|
|
||||||
} else {
|
|
||||||
parser->lenient_flags &= ~LENIENT_KEEP_ALIVE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Callbacks */
|
|
||||||
|
|
||||||
|
|
||||||
int llhttp__on_message_begin(llhttp_t* s, const char* p, const char* endp) {
|
|
||||||
int err;
|
|
||||||
CALLBACK_MAYBE(s, on_message_begin);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int llhttp__on_url(llhttp_t* s, const char* p, const char* endp) {
|
|
||||||
int err;
|
|
||||||
SPAN_CALLBACK_MAYBE(s, on_url, p, endp - p);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int llhttp__on_url_complete(llhttp_t* s, const char* p, const char* endp) {
|
|
||||||
int err;
|
|
||||||
CALLBACK_MAYBE(s, on_url_complete);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int llhttp__on_status(llhttp_t* s, const char* p, const char* endp) {
|
|
||||||
int err;
|
|
||||||
SPAN_CALLBACK_MAYBE(s, on_status, p, endp - p);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int llhttp__on_status_complete(llhttp_t* s, const char* p, const char* endp) {
|
|
||||||
int err;
|
|
||||||
CALLBACK_MAYBE(s, on_status_complete);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int llhttp__on_header_field(llhttp_t* s, const char* p, const char* endp) {
|
|
||||||
int err;
|
|
||||||
SPAN_CALLBACK_MAYBE(s, on_header_field, p, endp - p);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int llhttp__on_header_field_complete(llhttp_t* s, const char* p, const char* endp) {
|
|
||||||
int err;
|
|
||||||
CALLBACK_MAYBE(s, on_header_field_complete);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int llhttp__on_header_value(llhttp_t* s, const char* p, const char* endp) {
|
|
||||||
int err;
|
|
||||||
SPAN_CALLBACK_MAYBE(s, on_header_value, p, endp - p);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int llhttp__on_header_value_complete(llhttp_t* s, const char* p, const char* endp) {
|
|
||||||
int err;
|
|
||||||
CALLBACK_MAYBE(s, on_header_value_complete);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int llhttp__on_headers_complete(llhttp_t* s, const char* p, const char* endp) {
|
|
||||||
int err;
|
|
||||||
CALLBACK_MAYBE(s, on_headers_complete);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int llhttp__on_message_complete(llhttp_t* s, const char* p, const char* endp) {
|
|
||||||
int err;
|
|
||||||
CALLBACK_MAYBE(s, on_message_complete);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int llhttp__on_body(llhttp_t* s, const char* p, const char* endp) {
|
|
||||||
int err;
|
|
||||||
SPAN_CALLBACK_MAYBE(s, on_body, p, endp - p);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int llhttp__on_chunk_header(llhttp_t* s, const char* p, const char* endp) {
|
|
||||||
int err;
|
|
||||||
CALLBACK_MAYBE(s, on_chunk_header);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int llhttp__on_chunk_complete(llhttp_t* s, const char* p, const char* endp) {
|
|
||||||
int err;
|
|
||||||
CALLBACK_MAYBE(s, on_chunk_complete);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Private */
|
|
||||||
|
|
||||||
|
|
||||||
void llhttp__debug(llhttp_t* s, const char* p, const char* endp,
|
|
||||||
const char* msg) {
|
|
||||||
if (p == endp) {
|
|
||||||
fprintf(stderr, "p=%p type=%d flags=%02x next=null debug=%s\n", s, s->type,
|
|
||||||
s->flags, msg);
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "p=%p type=%d flags=%02x next=%02x debug=%s\n", s,
|
|
||||||
s->type, s->flags, *p, msg);
|
|
||||||
}
|
|
||||||
}
|
|
158
external/src/llhttp/http.c
vendored
158
external/src/llhttp/http.c
vendored
|
@ -1,158 +0,0 @@
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning(disable : 4100 4668 4710 4711 4820)
|
|
||||||
#elif defined __clang__
|
|
||||||
#pragma clang diagnostic ignored "-Wunused-parameter"
|
|
||||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
|
||||||
#elif defined __GNUC__
|
|
||||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#ifndef LLHTTP__TEST
|
|
||||||
# include "llhttp.h"
|
|
||||||
#else
|
|
||||||
# define llhttp_t llparse_t
|
|
||||||
#endif /* */
|
|
||||||
|
|
||||||
int llhttp_message_needs_eof(const llhttp_t* parser);
|
|
||||||
int llhttp_should_keep_alive(const llhttp_t* parser);
|
|
||||||
|
|
||||||
int llhttp__before_headers_complete(llhttp_t* parser, const char* p,
|
|
||||||
const char* endp) {
|
|
||||||
/* Set this here so that on_headers_complete() callbacks can see it */
|
|
||||||
if ((parser->flags & F_UPGRADE) &&
|
|
||||||
(parser->flags & F_CONNECTION_UPGRADE)) {
|
|
||||||
/* For responses, "Upgrade: foo" and "Connection: upgrade" are
|
|
||||||
* mandatory only when it is a 101 Switching Protocols response,
|
|
||||||
* otherwise it is purely informational, to announce support.
|
|
||||||
*/
|
|
||||||
parser->upgrade =
|
|
||||||
(parser->type == HTTP_REQUEST || parser->status_code == 101);
|
|
||||||
} else {
|
|
||||||
parser->upgrade = (parser->method == HTTP_CONNECT);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Return values:
|
|
||||||
* 0 - No body, `restart`, message_complete
|
|
||||||
* 1 - CONNECT request, `restart`, message_complete, and pause
|
|
||||||
* 2 - chunk_size_start
|
|
||||||
* 3 - body_identity
|
|
||||||
* 4 - body_identity_eof
|
|
||||||
* 5 - invalid transfer-encoding for request
|
|
||||||
*/
|
|
||||||
int llhttp__after_headers_complete(llhttp_t* parser, const char* p,
|
|
||||||
const char* endp) {
|
|
||||||
int hasBody;
|
|
||||||
|
|
||||||
hasBody = parser->flags & F_CHUNKED || parser->content_length > 0;
|
|
||||||
if (parser->upgrade && (parser->method == HTTP_CONNECT ||
|
|
||||||
(parser->flags & F_SKIPBODY) || !hasBody)) {
|
|
||||||
/* Exit, the rest of the message is in a different protocol. */
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parser->flags & F_SKIPBODY) {
|
|
||||||
return 0;
|
|
||||||
} else if (parser->flags & F_CHUNKED) {
|
|
||||||
/* chunked encoding - ignore Content-Length header, prepare for a chunk */
|
|
||||||
return 2;
|
|
||||||
} else if (parser->flags & F_TRANSFER_ENCODING) {
|
|
||||||
if (parser->type == HTTP_REQUEST &&
|
|
||||||
(parser->lenient_flags & LENIENT_CHUNKED_LENGTH) == 0) {
|
|
||||||
/* RFC 7230 3.3.3 */
|
|
||||||
|
|
||||||
/* If a Transfer-Encoding header field
|
|
||||||
* is present in a request and the chunked transfer coding is not
|
|
||||||
* the final encoding, the message body length cannot be determined
|
|
||||||
* reliably; the server MUST respond with the 400 (Bad Request)
|
|
||||||
* status code and then close the connection.
|
|
||||||
*/
|
|
||||||
return 5;
|
|
||||||
} else {
|
|
||||||
/* RFC 7230 3.3.3 */
|
|
||||||
|
|
||||||
/* If a Transfer-Encoding header field is present in a response and
|
|
||||||
* the chunked transfer coding is not the final encoding, the
|
|
||||||
* message body length is determined by reading the connection until
|
|
||||||
* it is closed by the server.
|
|
||||||
*/
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!(parser->flags & F_CONTENT_LENGTH)) {
|
|
||||||
if (!llhttp_message_needs_eof(parser)) {
|
|
||||||
/* Assume content-length 0 - read the next */
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
/* Read body until EOF */
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
} else if (parser->content_length == 0) {
|
|
||||||
/* Content-Length header given but zero: Content-Length: 0\r\n */
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
/* Content-Length header given and non-zero */
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int llhttp__after_message_complete(llhttp_t* parser, const char* p,
|
|
||||||
const char* endp) {
|
|
||||||
int should_keep_alive;
|
|
||||||
|
|
||||||
should_keep_alive = llhttp_should_keep_alive(parser);
|
|
||||||
parser->finish = HTTP_FINISH_SAFE;
|
|
||||||
parser->flags = 0;
|
|
||||||
|
|
||||||
/* NOTE: this is ignored in loose parsing mode */
|
|
||||||
return should_keep_alive;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int llhttp_message_needs_eof(const llhttp_t* parser) {
|
|
||||||
if (parser->type == HTTP_REQUEST) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* See RFC 2616 section 4.4 */
|
|
||||||
if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */
|
|
||||||
parser->status_code == 204 || /* No Content */
|
|
||||||
parser->status_code == 304 || /* Not Modified */
|
|
||||||
(parser->flags & F_SKIPBODY)) { /* response to a HEAD request */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* RFC 7230 3.3.3, see `llhttp__after_headers_complete` */
|
|
||||||
if ((parser->flags & F_TRANSFER_ENCODING) &&
|
|
||||||
(parser->flags & F_CHUNKED) == 0) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parser->flags & (F_CHUNKED | F_CONTENT_LENGTH)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int llhttp_should_keep_alive(const llhttp_t* parser) {
|
|
||||||
if (parser->http_major > 0 && parser->http_minor > 0) {
|
|
||||||
/* HTTP/1.1 */
|
|
||||||
if (parser->flags & F_CONNECTION_CLOSE) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* HTTP/1.0 or earlier */
|
|
||||||
if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return !llhttp_message_needs_eof(parser);
|
|
||||||
}
|
|
14943
external/src/llhttp/llhttp.c
vendored
14943
external/src/llhttp/llhttp.c
vendored
File diff suppressed because it is too large
Load diff
564
external/src/llhttp/llhttp.h
vendored
564
external/src/llhttp/llhttp.h
vendored
|
@ -1,564 +0,0 @@
|
||||||
#ifndef INCLUDE_LLHTTP_H_
|
|
||||||
#define INCLUDE_LLHTTP_H_
|
|
||||||
|
|
||||||
#define LLHTTP_VERSION_MAJOR 6
|
|
||||||
#define LLHTTP_VERSION_MINOR 0
|
|
||||||
#define LLHTTP_VERSION_PATCH 4
|
|
||||||
|
|
||||||
#ifndef LLHTTP_STRICT_MODE
|
|
||||||
# define LLHTTP_STRICT_MODE 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef INCLUDE_LLHTTP_ITSELF_H_
|
|
||||||
#define INCLUDE_LLHTTP_ITSELF_H_
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
typedef struct llhttp__internal_s llhttp__internal_t;
|
|
||||||
struct llhttp__internal_s {
|
|
||||||
int32_t _index;
|
|
||||||
void* _span_pos0;
|
|
||||||
void* _span_cb0;
|
|
||||||
int32_t error;
|
|
||||||
const char* reason;
|
|
||||||
const char* error_pos;
|
|
||||||
void* data;
|
|
||||||
void* _current;
|
|
||||||
uint64_t content_length;
|
|
||||||
uint8_t type;
|
|
||||||
uint8_t method;
|
|
||||||
uint8_t http_major;
|
|
||||||
uint8_t http_minor;
|
|
||||||
uint8_t header_state;
|
|
||||||
uint8_t lenient_flags;
|
|
||||||
uint8_t upgrade;
|
|
||||||
uint8_t finish;
|
|
||||||
uint16_t flags;
|
|
||||||
uint16_t status_code;
|
|
||||||
void* settings;
|
|
||||||
};
|
|
||||||
|
|
||||||
int llhttp__internal_init(llhttp__internal_t* s);
|
|
||||||
int llhttp__internal_execute(llhttp__internal_t* s, const char* p, const char* endp);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
#endif /* INCLUDE_LLHTTP_ITSELF_H_ */
|
|
||||||
|
|
||||||
#ifndef LLLLHTTP_C_HEADERS_
|
|
||||||
#define LLLLHTTP_C_HEADERS_
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum llhttp_errno {
|
|
||||||
HPE_OK = 0,
|
|
||||||
HPE_INTERNAL = 1,
|
|
||||||
HPE_STRICT = 2,
|
|
||||||
HPE_LF_EXPECTED = 3,
|
|
||||||
HPE_UNEXPECTED_CONTENT_LENGTH = 4,
|
|
||||||
HPE_CLOSED_CONNECTION = 5,
|
|
||||||
HPE_INVALID_METHOD = 6,
|
|
||||||
HPE_INVALID_URL = 7,
|
|
||||||
HPE_INVALID_CONSTANT = 8,
|
|
||||||
HPE_INVALID_VERSION = 9,
|
|
||||||
HPE_INVALID_HEADER_TOKEN = 10,
|
|
||||||
HPE_INVALID_CONTENT_LENGTH = 11,
|
|
||||||
HPE_INVALID_CHUNK_SIZE = 12,
|
|
||||||
HPE_INVALID_STATUS = 13,
|
|
||||||
HPE_INVALID_EOF_STATE = 14,
|
|
||||||
HPE_INVALID_TRANSFER_ENCODING = 15,
|
|
||||||
HPE_CB_MESSAGE_BEGIN = 16,
|
|
||||||
HPE_CB_HEADERS_COMPLETE = 17,
|
|
||||||
HPE_CB_MESSAGE_COMPLETE = 18,
|
|
||||||
HPE_CB_CHUNK_HEADER = 19,
|
|
||||||
HPE_CB_CHUNK_COMPLETE = 20,
|
|
||||||
HPE_PAUSED = 21,
|
|
||||||
HPE_PAUSED_UPGRADE = 22,
|
|
||||||
HPE_PAUSED_H2_UPGRADE = 23,
|
|
||||||
HPE_USER = 24
|
|
||||||
};
|
|
||||||
typedef enum llhttp_errno llhttp_errno_t;
|
|
||||||
|
|
||||||
enum llhttp_flags {
|
|
||||||
F_CONNECTION_KEEP_ALIVE = 0x1,
|
|
||||||
F_CONNECTION_CLOSE = 0x2,
|
|
||||||
F_CONNECTION_UPGRADE = 0x4,
|
|
||||||
F_CHUNKED = 0x8,
|
|
||||||
F_UPGRADE = 0x10,
|
|
||||||
F_CONTENT_LENGTH = 0x20,
|
|
||||||
F_SKIPBODY = 0x40,
|
|
||||||
F_TRAILING = 0x80,
|
|
||||||
F_TRANSFER_ENCODING = 0x200
|
|
||||||
};
|
|
||||||
typedef enum llhttp_flags llhttp_flags_t;
|
|
||||||
|
|
||||||
enum llhttp_lenient_flags {
|
|
||||||
LENIENT_HEADERS = 0x1,
|
|
||||||
LENIENT_CHUNKED_LENGTH = 0x2,
|
|
||||||
LENIENT_KEEP_ALIVE = 0x4
|
|
||||||
};
|
|
||||||
typedef enum llhttp_lenient_flags llhttp_lenient_flags_t;
|
|
||||||
|
|
||||||
enum llhttp_type {
|
|
||||||
HTTP_BOTH = 0,
|
|
||||||
HTTP_REQUEST = 1,
|
|
||||||
HTTP_RESPONSE = 2
|
|
||||||
};
|
|
||||||
typedef enum llhttp_type llhttp_type_t;
|
|
||||||
|
|
||||||
enum llhttp_finish {
|
|
||||||
HTTP_FINISH_SAFE = 0,
|
|
||||||
HTTP_FINISH_SAFE_WITH_CB = 1,
|
|
||||||
HTTP_FINISH_UNSAFE = 2
|
|
||||||
};
|
|
||||||
typedef enum llhttp_finish llhttp_finish_t;
|
|
||||||
|
|
||||||
enum llhttp_method {
|
|
||||||
HTTP_DELETE = 0,
|
|
||||||
HTTP_GET = 1,
|
|
||||||
HTTP_HEAD = 2,
|
|
||||||
HTTP_POST = 3,
|
|
||||||
HTTP_PUT = 4,
|
|
||||||
HTTP_CONNECT = 5,
|
|
||||||
HTTP_OPTIONS = 6,
|
|
||||||
HTTP_TRACE = 7,
|
|
||||||
HTTP_COPY = 8,
|
|
||||||
HTTP_LOCK = 9,
|
|
||||||
HTTP_MKCOL = 10,
|
|
||||||
HTTP_MOVE = 11,
|
|
||||||
HTTP_PROPFIND = 12,
|
|
||||||
HTTP_PROPPATCH = 13,
|
|
||||||
HTTP_SEARCH = 14,
|
|
||||||
HTTP_UNLOCK = 15,
|
|
||||||
HTTP_BIND = 16,
|
|
||||||
HTTP_REBIND = 17,
|
|
||||||
HTTP_UNBIND = 18,
|
|
||||||
HTTP_ACL = 19,
|
|
||||||
HTTP_REPORT = 20,
|
|
||||||
HTTP_MKACTIVITY = 21,
|
|
||||||
HTTP_CHECKOUT = 22,
|
|
||||||
HTTP_MERGE = 23,
|
|
||||||
HTTP_MSEARCH = 24,
|
|
||||||
HTTP_NOTIFY = 25,
|
|
||||||
HTTP_SUBSCRIBE = 26,
|
|
||||||
HTTP_UNSUBSCRIBE = 27,
|
|
||||||
HTTP_PATCH = 28,
|
|
||||||
HTTP_PURGE = 29,
|
|
||||||
HTTP_MKCALENDAR = 30,
|
|
||||||
HTTP_LINK = 31,
|
|
||||||
HTTP_UNLINK = 32,
|
|
||||||
HTTP_SOURCE = 33,
|
|
||||||
HTTP_PRI = 34,
|
|
||||||
HTTP_DESCRIBE = 35,
|
|
||||||
HTTP_ANNOUNCE = 36,
|
|
||||||
HTTP_SETUP = 37,
|
|
||||||
HTTP_PLAY = 38,
|
|
||||||
HTTP_PAUSE = 39,
|
|
||||||
HTTP_TEARDOWN = 40,
|
|
||||||
HTTP_GET_PARAMETER = 41,
|
|
||||||
HTTP_SET_PARAMETER = 42,
|
|
||||||
HTTP_REDIRECT = 43,
|
|
||||||
HTTP_RECORD = 44,
|
|
||||||
HTTP_FLUSH = 45
|
|
||||||
};
|
|
||||||
typedef enum llhttp_method llhttp_method_t;
|
|
||||||
|
|
||||||
#define HTTP_ERRNO_MAP(XX) \
|
|
||||||
XX(0, OK, OK) \
|
|
||||||
XX(1, INTERNAL, INTERNAL) \
|
|
||||||
XX(2, STRICT, STRICT) \
|
|
||||||
XX(3, LF_EXPECTED, LF_EXPECTED) \
|
|
||||||
XX(4, UNEXPECTED_CONTENT_LENGTH, UNEXPECTED_CONTENT_LENGTH) \
|
|
||||||
XX(5, CLOSED_CONNECTION, CLOSED_CONNECTION) \
|
|
||||||
XX(6, INVALID_METHOD, INVALID_METHOD) \
|
|
||||||
XX(7, INVALID_URL, INVALID_URL) \
|
|
||||||
XX(8, INVALID_CONSTANT, INVALID_CONSTANT) \
|
|
||||||
XX(9, INVALID_VERSION, INVALID_VERSION) \
|
|
||||||
XX(10, INVALID_HEADER_TOKEN, INVALID_HEADER_TOKEN) \
|
|
||||||
XX(11, INVALID_CONTENT_LENGTH, INVALID_CONTENT_LENGTH) \
|
|
||||||
XX(12, INVALID_CHUNK_SIZE, INVALID_CHUNK_SIZE) \
|
|
||||||
XX(13, INVALID_STATUS, INVALID_STATUS) \
|
|
||||||
XX(14, INVALID_EOF_STATE, INVALID_EOF_STATE) \
|
|
||||||
XX(15, INVALID_TRANSFER_ENCODING, INVALID_TRANSFER_ENCODING) \
|
|
||||||
XX(16, CB_MESSAGE_BEGIN, CB_MESSAGE_BEGIN) \
|
|
||||||
XX(17, CB_HEADERS_COMPLETE, CB_HEADERS_COMPLETE) \
|
|
||||||
XX(18, CB_MESSAGE_COMPLETE, CB_MESSAGE_COMPLETE) \
|
|
||||||
XX(19, CB_CHUNK_HEADER, CB_CHUNK_HEADER) \
|
|
||||||
XX(20, CB_CHUNK_COMPLETE, CB_CHUNK_COMPLETE) \
|
|
||||||
XX(21, PAUSED, PAUSED) \
|
|
||||||
XX(22, PAUSED_UPGRADE, PAUSED_UPGRADE) \
|
|
||||||
XX(23, PAUSED_H2_UPGRADE, PAUSED_H2_UPGRADE) \
|
|
||||||
XX(24, USER, USER) \
|
|
||||||
|
|
||||||
|
|
||||||
#define HTTP_METHOD_MAP(XX) \
|
|
||||||
XX(0, DELETE, DELETE) \
|
|
||||||
XX(1, GET, GET) \
|
|
||||||
XX(2, HEAD, HEAD) \
|
|
||||||
XX(3, POST, POST) \
|
|
||||||
XX(4, PUT, PUT) \
|
|
||||||
XX(5, CONNECT, CONNECT) \
|
|
||||||
XX(6, OPTIONS, OPTIONS) \
|
|
||||||
XX(7, TRACE, TRACE) \
|
|
||||||
XX(8, COPY, COPY) \
|
|
||||||
XX(9, LOCK, LOCK) \
|
|
||||||
XX(10, MKCOL, MKCOL) \
|
|
||||||
XX(11, MOVE, MOVE) \
|
|
||||||
XX(12, PROPFIND, PROPFIND) \
|
|
||||||
XX(13, PROPPATCH, PROPPATCH) \
|
|
||||||
XX(14, SEARCH, SEARCH) \
|
|
||||||
XX(15, UNLOCK, UNLOCK) \
|
|
||||||
XX(16, BIND, BIND) \
|
|
||||||
XX(17, REBIND, REBIND) \
|
|
||||||
XX(18, UNBIND, UNBIND) \
|
|
||||||
XX(19, ACL, ACL) \
|
|
||||||
XX(20, REPORT, REPORT) \
|
|
||||||
XX(21, MKACTIVITY, MKACTIVITY) \
|
|
||||||
XX(22, CHECKOUT, CHECKOUT) \
|
|
||||||
XX(23, MERGE, MERGE) \
|
|
||||||
XX(24, MSEARCH, M-SEARCH) \
|
|
||||||
XX(25, NOTIFY, NOTIFY) \
|
|
||||||
XX(26, SUBSCRIBE, SUBSCRIBE) \
|
|
||||||
XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \
|
|
||||||
XX(28, PATCH, PATCH) \
|
|
||||||
XX(29, PURGE, PURGE) \
|
|
||||||
XX(30, MKCALENDAR, MKCALENDAR) \
|
|
||||||
XX(31, LINK, LINK) \
|
|
||||||
XX(32, UNLINK, UNLINK) \
|
|
||||||
XX(33, SOURCE, SOURCE) \
|
|
||||||
|
|
||||||
|
|
||||||
#define RTSP_METHOD_MAP(XX) \
|
|
||||||
XX(1, GET, GET) \
|
|
||||||
XX(3, POST, POST) \
|
|
||||||
XX(6, OPTIONS, OPTIONS) \
|
|
||||||
XX(35, DESCRIBE, DESCRIBE) \
|
|
||||||
XX(36, ANNOUNCE, ANNOUNCE) \
|
|
||||||
XX(37, SETUP, SETUP) \
|
|
||||||
XX(38, PLAY, PLAY) \
|
|
||||||
XX(39, PAUSE, PAUSE) \
|
|
||||||
XX(40, TEARDOWN, TEARDOWN) \
|
|
||||||
XX(41, GET_PARAMETER, GET_PARAMETER) \
|
|
||||||
XX(42, SET_PARAMETER, SET_PARAMETER) \
|
|
||||||
XX(43, REDIRECT, REDIRECT) \
|
|
||||||
XX(44, RECORD, RECORD) \
|
|
||||||
XX(45, FLUSH, FLUSH) \
|
|
||||||
|
|
||||||
|
|
||||||
#define HTTP_ALL_METHOD_MAP(XX) \
|
|
||||||
XX(0, DELETE, DELETE) \
|
|
||||||
XX(1, GET, GET) \
|
|
||||||
XX(2, HEAD, HEAD) \
|
|
||||||
XX(3, POST, POST) \
|
|
||||||
XX(4, PUT, PUT) \
|
|
||||||
XX(5, CONNECT, CONNECT) \
|
|
||||||
XX(6, OPTIONS, OPTIONS) \
|
|
||||||
XX(7, TRACE, TRACE) \
|
|
||||||
XX(8, COPY, COPY) \
|
|
||||||
XX(9, LOCK, LOCK) \
|
|
||||||
XX(10, MKCOL, MKCOL) \
|
|
||||||
XX(11, MOVE, MOVE) \
|
|
||||||
XX(12, PROPFIND, PROPFIND) \
|
|
||||||
XX(13, PROPPATCH, PROPPATCH) \
|
|
||||||
XX(14, SEARCH, SEARCH) \
|
|
||||||
XX(15, UNLOCK, UNLOCK) \
|
|
||||||
XX(16, BIND, BIND) \
|
|
||||||
XX(17, REBIND, REBIND) \
|
|
||||||
XX(18, UNBIND, UNBIND) \
|
|
||||||
XX(19, ACL, ACL) \
|
|
||||||
XX(20, REPORT, REPORT) \
|
|
||||||
XX(21, MKACTIVITY, MKACTIVITY) \
|
|
||||||
XX(22, CHECKOUT, CHECKOUT) \
|
|
||||||
XX(23, MERGE, MERGE) \
|
|
||||||
XX(24, MSEARCH, M-SEARCH) \
|
|
||||||
XX(25, NOTIFY, NOTIFY) \
|
|
||||||
XX(26, SUBSCRIBE, SUBSCRIBE) \
|
|
||||||
XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \
|
|
||||||
XX(28, PATCH, PATCH) \
|
|
||||||
XX(29, PURGE, PURGE) \
|
|
||||||
XX(30, MKCALENDAR, MKCALENDAR) \
|
|
||||||
XX(31, LINK, LINK) \
|
|
||||||
XX(32, UNLINK, UNLINK) \
|
|
||||||
XX(33, SOURCE, SOURCE) \
|
|
||||||
XX(34, PRI, PRI) \
|
|
||||||
XX(35, DESCRIBE, DESCRIBE) \
|
|
||||||
XX(36, ANNOUNCE, ANNOUNCE) \
|
|
||||||
XX(37, SETUP, SETUP) \
|
|
||||||
XX(38, PLAY, PLAY) \
|
|
||||||
XX(39, PAUSE, PAUSE) \
|
|
||||||
XX(40, TEARDOWN, TEARDOWN) \
|
|
||||||
XX(41, GET_PARAMETER, GET_PARAMETER) \
|
|
||||||
XX(42, SET_PARAMETER, SET_PARAMETER) \
|
|
||||||
XX(43, REDIRECT, REDIRECT) \
|
|
||||||
XX(44, RECORD, RECORD) \
|
|
||||||
XX(45, FLUSH, FLUSH) \
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
#endif /* LLLLHTTP_C_HEADERS_ */
|
|
||||||
|
|
||||||
#ifndef INCLUDE_LLHTTP_API_H_
|
|
||||||
#define INCLUDE_LLHTTP_API_H_
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#if defined(__wasm__)
|
|
||||||
#define LLHTTP_EXPORT __attribute__((visibility("default")))
|
|
||||||
#else
|
|
||||||
#define LLHTTP_EXPORT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef llhttp__internal_t llhttp_t;
|
|
||||||
typedef struct llhttp_settings_s llhttp_settings_t;
|
|
||||||
|
|
||||||
typedef int (*llhttp_data_cb)(llhttp_t*, const char *at, size_t length);
|
|
||||||
typedef int (*llhttp_cb)(llhttp_t*);
|
|
||||||
|
|
||||||
struct llhttp_settings_s {
|
|
||||||
/* Possible return values 0, -1, `HPE_PAUSED` */
|
|
||||||
llhttp_cb on_message_begin;
|
|
||||||
|
|
||||||
/* Possible return values 0, -1, HPE_USER */
|
|
||||||
llhttp_data_cb on_url;
|
|
||||||
llhttp_data_cb on_status;
|
|
||||||
llhttp_data_cb on_header_field;
|
|
||||||
llhttp_data_cb on_header_value;
|
|
||||||
|
|
||||||
/* Possible return values:
|
|
||||||
* 0 - Proceed normally
|
|
||||||
* 1 - Assume that request/response has no body, and proceed to parsing the
|
|
||||||
* next message
|
|
||||||
* 2 - Assume absence of body (as above) and make `llhttp_execute()` return
|
|
||||||
* `HPE_PAUSED_UPGRADE`
|
|
||||||
* -1 - Error
|
|
||||||
* `HPE_PAUSED`
|
|
||||||
*/
|
|
||||||
llhttp_cb on_headers_complete;
|
|
||||||
|
|
||||||
/* Possible return values 0, -1, HPE_USER */
|
|
||||||
llhttp_data_cb on_body;
|
|
||||||
|
|
||||||
/* Possible return values 0, -1, `HPE_PAUSED` */
|
|
||||||
llhttp_cb on_message_complete;
|
|
||||||
|
|
||||||
/* When on_chunk_header is called, the current chunk length is stored
|
|
||||||
* in parser->content_length.
|
|
||||||
* Possible return values 0, -1, `HPE_PAUSED`
|
|
||||||
*/
|
|
||||||
llhttp_cb on_chunk_header;
|
|
||||||
llhttp_cb on_chunk_complete;
|
|
||||||
|
|
||||||
/* Information-only callbacks, return value is ignored */
|
|
||||||
llhttp_cb on_url_complete;
|
|
||||||
llhttp_cb on_status_complete;
|
|
||||||
llhttp_cb on_header_field_complete;
|
|
||||||
llhttp_cb on_header_value_complete;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Initialize the parser with specific type and user settings.
|
|
||||||
*
|
|
||||||
* NOTE: lifetime of `settings` has to be at least the same as the lifetime of
|
|
||||||
* the `parser` here. In practice, `settings` has to be either a static
|
|
||||||
* variable or be allocated with `malloc`, `new`, etc.
|
|
||||||
*/
|
|
||||||
LLHTTP_EXPORT
|
|
||||||
void llhttp_init(llhttp_t* parser, llhttp_type_t type,
|
|
||||||
const llhttp_settings_t* settings);
|
|
||||||
|
|
||||||
#if defined(__wasm__)
|
|
||||||
|
|
||||||
LLHTTP_EXPORT
|
|
||||||
llhttp_t* llhttp_alloc(llhttp_type_t type);
|
|
||||||
|
|
||||||
LLHTTP_EXPORT
|
|
||||||
void llhttp_free(llhttp_t* parser);
|
|
||||||
|
|
||||||
LLHTTP_EXPORT
|
|
||||||
uint8_t llhttp_get_type(llhttp_t* parser);
|
|
||||||
|
|
||||||
LLHTTP_EXPORT
|
|
||||||
uint8_t llhttp_get_http_major(llhttp_t* parser);
|
|
||||||
|
|
||||||
LLHTTP_EXPORT
|
|
||||||
uint8_t llhttp_get_http_minor(llhttp_t* parser);
|
|
||||||
|
|
||||||
LLHTTP_EXPORT
|
|
||||||
uint8_t llhttp_get_method(llhttp_t* parser);
|
|
||||||
|
|
||||||
LLHTTP_EXPORT
|
|
||||||
int llhttp_get_status_code(llhttp_t* parser);
|
|
||||||
|
|
||||||
LLHTTP_EXPORT
|
|
||||||
uint8_t llhttp_get_upgrade(llhttp_t* parser);
|
|
||||||
|
|
||||||
#endif // defined(__wasm__)
|
|
||||||
|
|
||||||
/* Reset an already initialized parser back to the start state, preserving the
|
|
||||||
* existing parser type, callback settings, user data, and lenient flags.
|
|
||||||
*/
|
|
||||||
LLHTTP_EXPORT
|
|
||||||
void llhttp_reset(llhttp_t* parser);
|
|
||||||
|
|
||||||
/* Initialize the settings object */
|
|
||||||
LLHTTP_EXPORT
|
|
||||||
void llhttp_settings_init(llhttp_settings_t* settings);
|
|
||||||
|
|
||||||
/* Parse full or partial request/response, invoking user callbacks along the
|
|
||||||
* way.
|
|
||||||
*
|
|
||||||
* If any of `llhttp_data_cb` returns errno not equal to `HPE_OK` - the parsing
|
|
||||||
* interrupts, and such errno is returned from `llhttp_execute()`. If
|
|
||||||
* `HPE_PAUSED` was used as a errno, the execution can be resumed with
|
|
||||||
* `llhttp_resume()` call.
|
|
||||||
*
|
|
||||||
* In a special case of CONNECT/Upgrade request/response `HPE_PAUSED_UPGRADE`
|
|
||||||
* is returned after fully parsing the request/response. If the user wishes to
|
|
||||||
* continue parsing, they need to invoke `llhttp_resume_after_upgrade()`.
|
|
||||||
*
|
|
||||||
* NOTE: if this function ever returns a non-pause type error, it will continue
|
|
||||||
* to return the same error upon each successive call up until `llhttp_init()`
|
|
||||||
* is called.
|
|
||||||
*/
|
|
||||||
LLHTTP_EXPORT
|
|
||||||
llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len);
|
|
||||||
|
|
||||||
/* This method should be called when the other side has no further bytes to
|
|
||||||
* send (e.g. shutdown of readable side of the TCP connection.)
|
|
||||||
*
|
|
||||||
* Requests without `Content-Length` and other messages might require treating
|
|
||||||
* all incoming bytes as the part of the body, up to the last byte of the
|
|
||||||
* connection. This method will invoke `on_message_complete()` callback if the
|
|
||||||
* request was terminated safely. Otherwise a error code would be returned.
|
|
||||||
*/
|
|
||||||
LLHTTP_EXPORT
|
|
||||||
llhttp_errno_t llhttp_finish(llhttp_t* parser);
|
|
||||||
|
|
||||||
/* Returns `1` if the incoming message is parsed until the last byte, and has
|
|
||||||
* to be completed by calling `llhttp_finish()` on EOF
|
|
||||||
*/
|
|
||||||
LLHTTP_EXPORT
|
|
||||||
int llhttp_message_needs_eof(const llhttp_t* parser);
|
|
||||||
|
|
||||||
/* Returns `1` if there might be any other messages following the last that was
|
|
||||||
* successfully parsed.
|
|
||||||
*/
|
|
||||||
LLHTTP_EXPORT
|
|
||||||
int llhttp_should_keep_alive(const llhttp_t* parser);
|
|
||||||
|
|
||||||
/* Make further calls of `llhttp_execute()` return `HPE_PAUSED` and set
|
|
||||||
* appropriate error reason.
|
|
||||||
*
|
|
||||||
* Important: do not call this from user callbacks! User callbacks must return
|
|
||||||
* `HPE_PAUSED` if pausing is required.
|
|
||||||
*/
|
|
||||||
LLHTTP_EXPORT
|
|
||||||
void llhttp_pause(llhttp_t* parser);
|
|
||||||
|
|
||||||
/* Might be called to resume the execution after the pause in user's callback.
|
|
||||||
* See `llhttp_execute()` above for details.
|
|
||||||
*
|
|
||||||
* Call this only if `llhttp_execute()` returns `HPE_PAUSED`.
|
|
||||||
*/
|
|
||||||
LLHTTP_EXPORT
|
|
||||||
void llhttp_resume(llhttp_t* parser);
|
|
||||||
|
|
||||||
/* Might be called to resume the execution after the pause in user's callback.
|
|
||||||
* See `llhttp_execute()` above for details.
|
|
||||||
*
|
|
||||||
* Call this only if `llhttp_execute()` returns `HPE_PAUSED_UPGRADE`
|
|
||||||
*/
|
|
||||||
LLHTTP_EXPORT
|
|
||||||
void llhttp_resume_after_upgrade(llhttp_t* parser);
|
|
||||||
|
|
||||||
/* Returns the latest return error */
|
|
||||||
LLHTTP_EXPORT
|
|
||||||
llhttp_errno_t llhttp_get_errno(const llhttp_t* parser);
|
|
||||||
|
|
||||||
/* Returns the verbal explanation of the latest returned error.
|
|
||||||
*
|
|
||||||
* Note: User callback should set error reason when returning the error. See
|
|
||||||
* `llhttp_set_error_reason()` for details.
|
|
||||||
*/
|
|
||||||
LLHTTP_EXPORT
|
|
||||||
const char* llhttp_get_error_reason(const llhttp_t* parser);
|
|
||||||
|
|
||||||
/* Assign verbal description to the returned error. Must be called in user
|
|
||||||
* callbacks right before returning the errno.
|
|
||||||
*
|
|
||||||
* Note: `HPE_USER` error code might be useful in user callbacks.
|
|
||||||
*/
|
|
||||||
LLHTTP_EXPORT
|
|
||||||
void llhttp_set_error_reason(llhttp_t* parser, const char* reason);
|
|
||||||
|
|
||||||
/* Returns the pointer to the last parsed byte before the returned error. The
|
|
||||||
* pointer is relative to the `data` argument of `llhttp_execute()`.
|
|
||||||
*
|
|
||||||
* Note: this method might be useful for counting the number of parsed bytes.
|
|
||||||
*/
|
|
||||||
LLHTTP_EXPORT
|
|
||||||
const char* llhttp_get_error_pos(const llhttp_t* parser);
|
|
||||||
|
|
||||||
/* Returns textual name of error code */
|
|
||||||
LLHTTP_EXPORT
|
|
||||||
const char* llhttp_errno_name(llhttp_errno_t err);
|
|
||||||
|
|
||||||
/* Returns textual name of HTTP method */
|
|
||||||
LLHTTP_EXPORT
|
|
||||||
const char* llhttp_method_name(llhttp_method_t method);
|
|
||||||
|
|
||||||
|
|
||||||
/* Enables/disables lenient header value parsing (disabled by default).
|
|
||||||
*
|
|
||||||
* Lenient parsing disables header value token checks, extending llhttp's
|
|
||||||
* protocol support to highly non-compliant clients/server. No
|
|
||||||
* `HPE_INVALID_HEADER_TOKEN` will be raised for incorrect header values when
|
|
||||||
* lenient parsing is "on".
|
|
||||||
*
|
|
||||||
* **(USE AT YOUR OWN RISK)**
|
|
||||||
*/
|
|
||||||
LLHTTP_EXPORT
|
|
||||||
void llhttp_set_lenient_headers(llhttp_t* parser, int enabled);
|
|
||||||
|
|
||||||
|
|
||||||
/* Enables/disables lenient handling of conflicting `Transfer-Encoding` and
|
|
||||||
* `Content-Length` headers (disabled by default).
|
|
||||||
*
|
|
||||||
* Normally `llhttp` would error when `Transfer-Encoding` is present in
|
|
||||||
* conjunction with `Content-Length`. This error is important to prevent HTTP
|
|
||||||
* request smuggling, but may be less desirable for small number of cases
|
|
||||||
* involving legacy servers.
|
|
||||||
*
|
|
||||||
* **(USE AT YOUR OWN RISK)**
|
|
||||||
*/
|
|
||||||
LLHTTP_EXPORT
|
|
||||||
void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled);
|
|
||||||
|
|
||||||
|
|
||||||
/* Enables/disables lenient handling of `Connection: close` and HTTP/1.0
|
|
||||||
* requests responses.
|
|
||||||
*
|
|
||||||
* Normally `llhttp` would error on (in strict mode) or discard (in loose mode)
|
|
||||||
* the HTTP request/response after the request/response with `Connection: close`
|
|
||||||
* and `Content-Length`. This is important to prevent cache poisoning attacks,
|
|
||||||
* but might interact badly with outdated and insecure clients. With this flag
|
|
||||||
* the extra request/response will be parsed normally.
|
|
||||||
*
|
|
||||||
* **(USE AT YOUR OWN RISK)**
|
|
||||||
*/
|
|
||||||
void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
#endif /* INCLUDE_LLHTTP_API_H_ */
|
|
||||||
|
|
||||||
#endif /* INCLUDE_LLHTTP_H_ */
|
|
|
@ -232,6 +232,7 @@ void ConsoleCommands::run()
|
||||||
|
|
||||||
if (std::cin.eof()) {
|
if (std::cin.eof()) {
|
||||||
LOGINFO(1, "EOF, stopping");
|
LOGINFO(1, "EOF, stopping");
|
||||||
|
do_exit(m_pool, nullptr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,235 +18,318 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "uv_util.h"
|
#include "uv_util.h"
|
||||||
#include "json_rpc_request.h"
|
#include "json_rpc_request.h"
|
||||||
#include "llhttp.h"
|
#include <curl/curl.h>
|
||||||
#include <string>
|
|
||||||
|
|
||||||
static constexpr char log_category_prefix[] = "JSONRPCRequest ";
|
static constexpr char log_category_prefix[] = "JSONRPCRequest ";
|
||||||
|
|
||||||
namespace p2pool {
|
namespace p2pool {
|
||||||
|
namespace JSONRPCRequest {
|
||||||
|
|
||||||
JSONRPCRequest::JSONRPCRequest(const char* address, int port, const char* req, CallbackBase* cb, CallbackBase* close_cb, uv_loop_t* loop)
|
struct CurlContext
|
||||||
: m_socket{}
|
{
|
||||||
, m_connect{}
|
CurlContext(const std::string& address, int port, const std::string& req, const std::string& auth, CallbackBase* cb, CallbackBase* close_cb, uv_loop_t* loop);
|
||||||
, m_write{}
|
~CurlContext();
|
||||||
|
|
||||||
|
static int socket_func(CURL* easy, curl_socket_t s, int action, void* userp, void* socketp)
|
||||||
|
{
|
||||||
|
CurlContext* ctx = reinterpret_cast<CurlContext*>(socketp ? socketp : userp);
|
||||||
|
return ctx->on_socket(easy, s, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int timer_func(CURLM* multi, long timeout_ms, void* ctx)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<CurlContext*>(ctx)->on_timer(multi, timeout_ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t write_func(const void* buffer, size_t size, size_t count, void* ctx)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<CurlContext*>(ctx)->on_write(buffer, size, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
int on_socket(CURL* easy, curl_socket_t s, int action);
|
||||||
|
int on_timer(CURLM* multi, long timeout_ms);
|
||||||
|
|
||||||
|
static void on_timeout(uv_handle_t* req);
|
||||||
|
|
||||||
|
size_t on_write(const void* buffer, size_t size, size_t count);
|
||||||
|
|
||||||
|
static void curl_perform(uv_poll_t* req, int status, int events);
|
||||||
|
void check_multi_info();
|
||||||
|
|
||||||
|
static void on_close(uv_handle_t* h);
|
||||||
|
|
||||||
|
uv_poll_t m_pollHandle;
|
||||||
|
curl_socket_t m_socket;
|
||||||
|
|
||||||
|
CallbackBase* m_callback;
|
||||||
|
CallbackBase* m_closeCallback;
|
||||||
|
|
||||||
|
uv_loop_t* m_loop;
|
||||||
|
uv_timer_t m_timer;
|
||||||
|
uv_async_t m_async;
|
||||||
|
CURLM* m_multiHandle;
|
||||||
|
CURL* m_handle;
|
||||||
|
|
||||||
|
std::string m_url;
|
||||||
|
std::string m_req;
|
||||||
|
std::string m_auth;
|
||||||
|
|
||||||
|
std::vector<char> m_response;
|
||||||
|
std::string m_error;
|
||||||
|
};
|
||||||
|
|
||||||
|
CurlContext::CurlContext(const std::string& address, int port, const std::string& req, const std::string& auth, CallbackBase* cb, CallbackBase* close_cb, uv_loop_t* loop)
|
||||||
|
: m_pollHandle{}
|
||||||
|
, m_socket{}
|
||||||
, m_callback(cb)
|
, m_callback(cb)
|
||||||
, m_closeCallback(close_cb)
|
, m_closeCallback(close_cb)
|
||||||
, m_contentLength(0)
|
, m_loop(loop)
|
||||||
, m_contentLengthHeader(false)
|
, m_timer{}
|
||||||
, m_readBufInUse(false)
|
, m_async{}
|
||||||
, m_valid(true)
|
, m_multiHandle(nullptr)
|
||||||
|
, m_handle(nullptr)
|
||||||
|
, m_req(req)
|
||||||
|
, m_auth(auth)
|
||||||
{
|
{
|
||||||
m_readBuf[0] = '\0';
|
{
|
||||||
|
char buf[log::Stream::BUF_SIZE + 1];
|
||||||
|
buf[0] = '\0';
|
||||||
|
|
||||||
uv_tcp_init(loop ? loop : uv_default_loop_checked(), &m_socket);
|
log::Stream s(buf);
|
||||||
uv_tcp_nodelay(&m_socket, 1);
|
s << "http://" << address << ':' << port;
|
||||||
|
|
||||||
sockaddr_storage addr;
|
if (!m_req.empty() && (m_req.front() == '/')) {
|
||||||
if (uv_ip4_addr(address, port, reinterpret_cast<sockaddr_in*>(&addr)) != 0) {
|
s << m_req.c_str() << '\0';
|
||||||
const int err = uv_ip6_addr(address, port, reinterpret_cast<sockaddr_in6*>(&addr));
|
m_req.clear();
|
||||||
if (err) {
|
|
||||||
LOGERR(1, "invalid IP address " << address << " or port " << port);
|
|
||||||
m_valid = false;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
s << "/json_rpc\0";
|
||||||
|
}
|
||||||
|
|
||||||
|
m_url = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_socket.data = this;
|
int err = uv_timer_init(m_loop, &m_timer);
|
||||||
m_connect.data = this;
|
|
||||||
m_write.data = this;
|
|
||||||
|
|
||||||
const char* uri = "/json_rpc";
|
|
||||||
|
|
||||||
size_t len = req ? strlen(req) : 0;
|
|
||||||
if (!len) {
|
|
||||||
LOGERR(1, "Empty JSONRPCRequest, fix the code!");
|
|
||||||
m_valid = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (req[0] == '/') {
|
|
||||||
uri = req;
|
|
||||||
len = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_request.reserve(std::max<size_t>(len + 128, log::Stream::BUF_SIZE + 1));
|
|
||||||
m_request.resize(log::Stream::BUF_SIZE + 1);
|
|
||||||
|
|
||||||
log::Stream s(m_request.data(), m_request.size());
|
|
||||||
s << "POST " << uri << " HTTP/1.1\nContent-Type: application/json\nContent-Length: " << len << "\n\n";
|
|
||||||
|
|
||||||
m_request.resize(s.m_pos);
|
|
||||||
m_request.insert(m_request.end(), req, req + len);
|
|
||||||
|
|
||||||
m_response.reserve(sizeof(m_readBuf));
|
|
||||||
|
|
||||||
const int err = uv_tcp_connect(&m_connect, &m_socket, reinterpret_cast<const sockaddr*>(&addr), on_connect);
|
|
||||||
if (err) {
|
if (err) {
|
||||||
LOGERR(1, "failed to initiate tcp connection to " << address << ", error " << uv_err_name(err));
|
LOGERR(1, "uv_timer_init failed, error " << uv_err_name(err));
|
||||||
m_valid = false;
|
throw std::runtime_error("uv_timer_init failed");
|
||||||
|
}
|
||||||
|
m_timer.data = this;
|
||||||
|
|
||||||
|
err = uv_async_init(m_loop, &m_async, reinterpret_cast<uv_async_cb>(on_timeout));
|
||||||
|
if (err) {
|
||||||
|
LOGERR(1, "uv_async_init failed, error " << uv_err_name(err));
|
||||||
|
uv_close(reinterpret_cast<uv_handle_t*>(&m_timer), nullptr);
|
||||||
|
throw std::runtime_error("uv_async_init failed");
|
||||||
|
}
|
||||||
|
m_async.data = this;
|
||||||
|
|
||||||
|
m_multiHandle = curl_multi_init();
|
||||||
|
if (!m_multiHandle) {
|
||||||
|
constexpr char msg[] = "curl_multi_init() failed";
|
||||||
|
LOGERR(1, msg);
|
||||||
|
uv_close(reinterpret_cast<uv_handle_t*>(&m_async), nullptr);
|
||||||
|
uv_close(reinterpret_cast<uv_handle_t*>(&m_timer), nullptr);
|
||||||
|
throw std::runtime_error(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_multi_setopt(m_multiHandle, CURLMOPT_SOCKETFUNCTION, socket_func);
|
||||||
|
curl_multi_setopt(m_multiHandle, CURLMOPT_SOCKETDATA, this);
|
||||||
|
|
||||||
|
curl_multi_setopt(m_multiHandle, CURLMOPT_TIMERFUNCTION, timer_func);
|
||||||
|
curl_multi_setopt(m_multiHandle, CURLMOPT_TIMERDATA, this);
|
||||||
|
|
||||||
|
m_handle = curl_easy_init();
|
||||||
|
if (!m_handle) {
|
||||||
|
constexpr char msg[] = "curl_easy_init() failed";
|
||||||
|
LOGERR(1, msg);
|
||||||
|
curl_multi_cleanup(m_multiHandle);
|
||||||
|
uv_close(reinterpret_cast<uv_handle_t*>(&m_async), nullptr);
|
||||||
|
uv_close(reinterpret_cast<uv_handle_t*>(&m_timer), nullptr);
|
||||||
|
throw std::runtime_error(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_easy_setopt(m_handle, CURLOPT_WRITEFUNCTION, write_func);
|
||||||
|
curl_easy_setopt(m_handle, CURLOPT_WRITEDATA, this);
|
||||||
|
|
||||||
|
curl_easy_setopt(m_handle, CURLOPT_URL, m_url.c_str());
|
||||||
|
curl_easy_setopt(m_handle, CURLOPT_POSTFIELDS, m_req.c_str());
|
||||||
|
curl_easy_setopt(m_handle, CURLOPT_CONNECTTIMEOUT, 1);
|
||||||
|
curl_easy_setopt(m_handle, CURLOPT_TIMEOUT, 10);
|
||||||
|
|
||||||
|
if (!m_auth.empty()) {
|
||||||
|
curl_easy_setopt(m_handle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST | CURLAUTH_ONLY);
|
||||||
|
curl_easy_setopt(m_handle, CURLOPT_USERPWD, m_auth.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
CURLMcode curl_err = curl_multi_add_handle(m_multiHandle, m_handle);
|
||||||
|
if (curl_err != CURLM_OK) {
|
||||||
|
LOGERR(1, "curl_multi_add_handle failed, error " << curl_multi_strerror(curl_err));
|
||||||
|
curl_easy_cleanup(m_handle);
|
||||||
|
curl_multi_cleanup(m_multiHandle);
|
||||||
|
uv_close(reinterpret_cast<uv_handle_t*>(&m_async), nullptr);
|
||||||
|
uv_close(reinterpret_cast<uv_handle_t*>(&m_timer), nullptr);
|
||||||
|
throw std::runtime_error("curl_multi_add_handle failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JSONRPCRequest::on_connect(uv_connect_t* req, int status)
|
CurlContext::~CurlContext()
|
||||||
{
|
{
|
||||||
JSONRPCRequest* pThis = static_cast<JSONRPCRequest*>(req->data);
|
if (m_error.empty() && !m_response.empty()) {
|
||||||
|
(*m_callback)(m_response.data(), m_response.size());
|
||||||
if (status != 0) {
|
|
||||||
pThis->m_error = uv_err_name(status);
|
|
||||||
LOGERR(1, "failed to connect, error " << pThis->m_error);
|
|
||||||
pThis->close();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uv_buf_t buf[1];
|
|
||||||
buf[0].base = pThis->m_request.data();
|
|
||||||
buf[0].len = static_cast<uint32_t>(pThis->m_request.size());
|
|
||||||
|
|
||||||
uv_write(&pThis->m_write, reinterpret_cast<uv_stream_t*>(&pThis->m_socket), buf, 1, on_write);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JSONRPCRequest::on_write(uv_write_t* handle, int status)
|
|
||||||
{
|
|
||||||
JSONRPCRequest* pThis = static_cast<JSONRPCRequest*>(handle->data);
|
|
||||||
|
|
||||||
if (status != 0) {
|
|
||||||
pThis->m_error = uv_err_name(status);
|
|
||||||
LOGERR(1, "failed to send request, error " << pThis->m_error);
|
|
||||||
pThis->close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uv_read_start(reinterpret_cast<uv_stream_t*>(&pThis->m_socket), on_alloc, on_read);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JSONRPCRequest::on_alloc(uv_handle_t* handle, size_t /*suggested_size*/, uv_buf_t* buf)
|
|
||||||
{
|
|
||||||
JSONRPCRequest* pThis = static_cast<JSONRPCRequest*>(handle->data);
|
|
||||||
|
|
||||||
if (pThis->m_readBufInUse) {
|
|
||||||
LOGERR(1, "read buffer is already in use");
|
|
||||||
}
|
|
||||||
|
|
||||||
buf->len = sizeof(pThis->m_readBuf);
|
|
||||||
buf->base = pThis->m_readBuf;
|
|
||||||
pThis->m_readBufInUse = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void JSONRPCRequest::on_read(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf)
|
|
||||||
{
|
|
||||||
JSONRPCRequest* pThis = static_cast<JSONRPCRequest*>(stream->data);
|
|
||||||
pThis->m_readBufInUse = false;
|
|
||||||
|
|
||||||
if (nread > 0) {
|
|
||||||
pThis->on_read(buf->base, nread);
|
|
||||||
}
|
|
||||||
else if (nread < 0) {
|
|
||||||
if (nread != UV_EOF){
|
|
||||||
pThis->m_error = uv_err_name(static_cast<int>(nread));
|
|
||||||
LOGERR(1, "failed to read response, error " << pThis->m_error);
|
|
||||||
}
|
|
||||||
pThis->close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void JSONRPCRequest::on_read(const char* data, size_t size)
|
|
||||||
{
|
|
||||||
m_response.append(data, size);
|
|
||||||
|
|
||||||
static constexpr char headers_end[] = "\r\n\r\n";
|
|
||||||
if (m_response.find(headers_end) == std::string::npos) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
llhttp_settings_t settings{};
|
|
||||||
|
|
||||||
settings.on_status = [](llhttp_t*, const char* at, size_t length)
|
|
||||||
{
|
|
||||||
if ((length == 2) && (!memcmp(at, "Ok", 2) || !memcmp(at, "OK", 2))) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
};
|
|
||||||
|
|
||||||
settings.on_header_field = [](llhttp_t* parser, const char* at, size_t length)
|
|
||||||
{
|
|
||||||
JSONRPCRequest* pThis = static_cast<JSONRPCRequest*>(parser->data);
|
|
||||||
static const char header[] = "Content-Length";
|
|
||||||
pThis->m_contentLengthHeader = ((length == sizeof(header) - 1) && (memcmp(at, header, length) == 0));
|
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
settings.on_header_value = [](llhttp_t* parser, const char* at, size_t length)
|
|
||||||
{
|
|
||||||
JSONRPCRequest* pThis = static_cast<JSONRPCRequest*>(parser->data);
|
|
||||||
if (pThis->m_contentLengthHeader) {
|
|
||||||
uint32_t k = 0;
|
|
||||||
for (const char* p = at; p < at + length; ++p) {
|
|
||||||
if ('0' <= *p && *p <= '9') {
|
|
||||||
k = k * 10 + (*p - '0');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!k) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
pThis->m_contentLength = k;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
settings.on_body = [](llhttp_t* parser, const char* at, size_t length)
|
|
||||||
{
|
|
||||||
JSONRPCRequest* pThis = static_cast<JSONRPCRequest*>(parser->data);
|
|
||||||
if (pThis->m_contentLength && (length >= pThis->m_contentLength) && pThis->m_callback) {
|
|
||||||
(*pThis->m_callback)(at, length);
|
|
||||||
delete pThis->m_callback;
|
|
||||||
pThis->m_callback = nullptr;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
llhttp_t parser;
|
|
||||||
llhttp_init(&parser, HTTP_RESPONSE, &settings);
|
|
||||||
|
|
||||||
parser.data = this;
|
|
||||||
|
|
||||||
const llhttp_errno result = llhttp_execute(&parser, m_response.c_str(), m_response.length());
|
|
||||||
if (result != HPE_OK) {
|
|
||||||
m_error = "failed to parse response";
|
|
||||||
LOGERR(1, m_error << ", result = " << static_cast<int>(result));
|
|
||||||
close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_callback) {
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void JSONRPCRequest::close()
|
|
||||||
{
|
|
||||||
uv_handle_t* h = reinterpret_cast<uv_handle_t*>(&m_socket);
|
|
||||||
if (!uv_is_closing(h)) {
|
|
||||||
uv_close(h, on_close);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void JSONRPCRequest::on_close(uv_handle_t* handle)
|
|
||||||
{
|
|
||||||
JSONRPCRequest* req = static_cast<JSONRPCRequest*>(handle->data);
|
|
||||||
if (req->m_closeCallback) {
|
|
||||||
(*req->m_closeCallback)(req->m_error.c_str(), req->m_error.length());
|
|
||||||
}
|
|
||||||
delete req;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONRPCRequest::~JSONRPCRequest()
|
|
||||||
{
|
|
||||||
delete m_callback;
|
delete m_callback;
|
||||||
|
|
||||||
|
(*m_closeCallback)(m_error.c_str(), m_error.length());
|
||||||
delete m_closeCallback;
|
delete m_closeCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CurlContext::on_socket(CURL* /*easy*/, curl_socket_t s, int action)
|
||||||
|
{
|
||||||
|
switch (action) {
|
||||||
|
case CURL_POLL_IN:
|
||||||
|
case CURL_POLL_OUT:
|
||||||
|
case CURL_POLL_INOUT:
|
||||||
|
{
|
||||||
|
if (!m_socket) {
|
||||||
|
m_socket = s;
|
||||||
|
curl_multi_assign(m_multiHandle, s, this);
|
||||||
|
}
|
||||||
|
else if (m_socket != s) {
|
||||||
|
LOGERR(1, "This code can't work with multiple parallel requests. Fix the code!");
|
||||||
|
}
|
||||||
|
|
||||||
|
int events = 0;
|
||||||
|
if (action != CURL_POLL_IN) events |= UV_WRITABLE;
|
||||||
|
if (action != CURL_POLL_OUT) events |= UV_READABLE;
|
||||||
|
|
||||||
|
if (!m_pollHandle.data) {
|
||||||
|
uv_poll_init_socket(m_loop, &m_pollHandle, s);
|
||||||
|
m_pollHandle.data = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
uv_poll_start(&m_pollHandle, events, curl_perform);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CURL_POLL_REMOVE:
|
||||||
|
default:
|
||||||
|
curl_multi_assign(m_multiHandle, s, nullptr);
|
||||||
|
uv_poll_stop(&m_pollHandle);
|
||||||
|
uv_close(reinterpret_cast<uv_handle_t*>(&m_async), on_close);
|
||||||
|
uv_close(reinterpret_cast<uv_handle_t*>(&m_timer), on_close);
|
||||||
|
uv_close(reinterpret_cast<uv_handle_t*>(&m_pollHandle), on_close);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CurlContext::on_timer(CURLM* /*multi*/, long timeout_ms)
|
||||||
|
{
|
||||||
|
if (timeout_ms < 0) {
|
||||||
|
uv_timer_stop(&m_timer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeout_ms == 0) {
|
||||||
|
// 0 ms timeout, but we can't just call on_timeout() here - we have to kick the UV loop
|
||||||
|
uv_async_send(&m_async);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uv_timer_start(&m_timer, reinterpret_cast<uv_timer_cb>(on_timeout), timeout_ms, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurlContext::on_timeout(uv_handle_t* req)
|
||||||
|
{
|
||||||
|
CurlContext* ctx = reinterpret_cast<CurlContext*>(req->data);
|
||||||
|
|
||||||
|
int running_handles;
|
||||||
|
curl_multi_socket_action(ctx->m_multiHandle, CURL_SOCKET_TIMEOUT, 0, &running_handles);
|
||||||
|
ctx->check_multi_info();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t CurlContext::on_write(const void* buffer, size_t size, size_t count)
|
||||||
|
{
|
||||||
|
const char* p = reinterpret_cast<const char*>(buffer);
|
||||||
|
m_response.insert(m_response.end(), p, p + size * count);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurlContext::curl_perform(uv_poll_t* req, int status, int events)
|
||||||
|
{
|
||||||
|
int flags = 0;
|
||||||
|
if (status < 0) {
|
||||||
|
flags |= CURL_CSELECT_ERR;
|
||||||
|
LOGERR(1, "uv_poll_start returned error " << uv_err_name(status));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (events & UV_READABLE) flags |= CURL_CSELECT_IN;
|
||||||
|
if (events & UV_WRITABLE) flags |= CURL_CSELECT_OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
CurlContext* ctx = reinterpret_cast<CurlContext*>(req->data);
|
||||||
|
|
||||||
|
int running_handles;
|
||||||
|
curl_multi_socket_action(ctx->m_multiHandle, ctx->m_socket, flags, &running_handles);
|
||||||
|
ctx->check_multi_info();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurlContext::check_multi_info()
|
||||||
|
{
|
||||||
|
int pending;
|
||||||
|
while (CURLMsg* message = curl_multi_info_read(m_multiHandle, &pending)) {
|
||||||
|
if (message->msg == CURLMSG_DONE) {
|
||||||
|
if ((message->data.result != CURLE_OK) || m_response.empty()) {
|
||||||
|
m_error = m_response.empty() ? "empty response" : curl_easy_strerror(message->data.result);
|
||||||
|
}
|
||||||
|
|
||||||
|
long http_code = 0;
|
||||||
|
curl_easy_getinfo(message->easy_handle, CURLINFO_RESPONSE_CODE, &http_code);
|
||||||
|
|
||||||
|
if (http_code != 200) {
|
||||||
|
char buf[32] = {};
|
||||||
|
log::Stream s(buf);
|
||||||
|
s << "HTTP error " << static_cast<int>(http_code) << '\0';
|
||||||
|
m_error = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_multi_remove_handle(m_multiHandle, m_handle);
|
||||||
|
curl_easy_cleanup(m_handle);
|
||||||
|
curl_multi_cleanup(m_multiHandle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurlContext::on_close(uv_handle_t* h)
|
||||||
|
{
|
||||||
|
CurlContext* ctx = reinterpret_cast<CurlContext*>(h->data);
|
||||||
|
h->data = nullptr;
|
||||||
|
|
||||||
|
if (ctx->m_timer.data || ctx->m_async.data || ctx->m_pollHandle.data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Call(const std::string& address, int port, const std::string& req, const std::string& auth, CallbackBase* cb, CallbackBase* close_cb, uv_loop_t* loop)
|
||||||
|
{
|
||||||
|
CallOnLoop(loop,
|
||||||
|
[=]()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
new CurlContext(address, port, req, auth, cb, close_cb, loop);
|
||||||
|
}
|
||||||
|
catch (const std::exception& e) {
|
||||||
|
const char* msg = e.what();
|
||||||
|
(*close_cb)(msg, strlen(msg));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace JSONRPCRequest
|
||||||
} // namespace p2pool
|
} // namespace p2pool
|
||||||
|
|
|
@ -18,78 +18,32 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace p2pool {
|
namespace p2pool {
|
||||||
|
namespace JSONRPCRequest {
|
||||||
|
|
||||||
class JSONRPCRequest
|
struct CallbackBase
|
||||||
{
|
{
|
||||||
public:
|
virtual ~CallbackBase() {}
|
||||||
template<typename T>
|
virtual void operator()(const char* data, size_t size) = 0;
|
||||||
static FORCEINLINE void call(const char* address, int port, const char* req, T&& cb)
|
|
||||||
{
|
|
||||||
// It will be deleted in one of the tcp callbacks eventually
|
|
||||||
JSONRPCRequest* r = new JSONRPCRequest(address, port, req, new Callback<T>(std::move(cb)), nullptr, nullptr);
|
|
||||||
if (!r->m_valid) {
|
|
||||||
delete r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename U>
|
|
||||||
static FORCEINLINE void call(const char* address, int port, const char* req, T&& cb, U&& close_cb, uv_loop_t* loop = nullptr)
|
|
||||||
{
|
|
||||||
// It will be deleted in one of the tcp callbacks eventually
|
|
||||||
CallbackBase* close_callback = new Callback<U>(std::move(close_cb));
|
|
||||||
JSONRPCRequest* r = new JSONRPCRequest(address, port, req, new Callback<T>(std::move(cb)), close_callback, loop);
|
|
||||||
if (!r->m_valid) {
|
|
||||||
constexpr char err[] = "internal error";
|
|
||||||
(*close_callback)(err, sizeof(err) - 1);
|
|
||||||
delete r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct CallbackBase
|
|
||||||
{
|
|
||||||
virtual ~CallbackBase() {}
|
|
||||||
virtual void operator()(const char* data, size_t size) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct Callback : public CallbackBase
|
|
||||||
{
|
|
||||||
explicit FORCEINLINE Callback(T&& cb) : m_cb(std::move(cb)) {}
|
|
||||||
void operator()(const char* data, size_t size) override { m_cb(data, size); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
Callback& operator=(Callback&&) = delete;
|
|
||||||
T m_cb;
|
|
||||||
};
|
|
||||||
|
|
||||||
JSONRPCRequest(const char* address, int port, const char* req, CallbackBase* cb, CallbackBase* close_cb, uv_loop_t* loop);
|
|
||||||
~JSONRPCRequest();
|
|
||||||
|
|
||||||
static void on_connect(uv_connect_t* req, int status);
|
|
||||||
static void on_write(uv_write_t* handle, int status);
|
|
||||||
static void on_alloc(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf);
|
|
||||||
static void on_read(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf);
|
|
||||||
void on_read(const char* data, size_t size);
|
|
||||||
// cppcheck-suppress functionConst
|
|
||||||
void close();
|
|
||||||
static void on_close(uv_handle_t* handle);
|
|
||||||
|
|
||||||
uv_tcp_t m_socket;
|
|
||||||
uv_connect_t m_connect;
|
|
||||||
uv_write_t m_write;
|
|
||||||
|
|
||||||
CallbackBase* m_callback;
|
|
||||||
CallbackBase* m_closeCallback;
|
|
||||||
uint32_t m_contentLength;
|
|
||||||
bool m_contentLengthHeader;
|
|
||||||
|
|
||||||
std::vector<char> m_request;
|
|
||||||
std::string m_response;
|
|
||||||
char m_readBuf[65536];
|
|
||||||
bool m_readBufInUse;
|
|
||||||
bool m_valid;
|
|
||||||
std::string m_error;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct Callback : public CallbackBase
|
||||||
|
{
|
||||||
|
explicit FORCEINLINE Callback(T&& cb) : m_cb(std::move(cb)) {}
|
||||||
|
void operator()(const char* data, size_t size) override { m_cb(data, size); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Callback& operator=(Callback&&) = delete;
|
||||||
|
T m_cb;
|
||||||
|
};
|
||||||
|
|
||||||
|
void Call(const std::string& address, int port, const std::string& req, const std::string& auth, CallbackBase* cb, CallbackBase* close_cb, uv_loop_t* loop);
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
FORCEINLINE void call(const std::string& address, int port, const std::string& req, const std::string& auth, T&& cb, U&& close_cb, uv_loop_t* loop = uv_default_loop_checked())
|
||||||
|
{
|
||||||
|
Call(address, port, req, auth, new Callback<T>(std::move(cb)), new Callback<U>(std::move(close_cb)), loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace JSONRPCRequest
|
||||||
} // namespace p2pool
|
} // namespace p2pool
|
||||||
|
|
|
@ -46,6 +46,7 @@ void p2pool_usage()
|
||||||
"--start-mining N Start built-in miner using N threads (any value between 1 and 64)\n"
|
"--start-mining N Start built-in miner using N threads (any value between 1 and 64)\n"
|
||||||
"--mini Connect to p2pool-mini sidechain. Note that it will also change default p2p port from %d to %d\n"
|
"--mini Connect to p2pool-mini sidechain. Note that it will also change default p2p port from %d to %d\n"
|
||||||
"--no-autodiff Disable automatic difficulty adjustment for miners connected to stratum\n"
|
"--no-autodiff Disable automatic difficulty adjustment for miners connected to stratum\n"
|
||||||
|
"--rpc-login Specify username[:password] required for Monero RPC server\n"
|
||||||
"--help Show this help message\n\n"
|
"--help Show this help message\n\n"
|
||||||
"Example command line:\n\n"
|
"Example command line:\n\n"
|
||||||
"%s --host 127.0.0.1 --rpc-port 18081 --zmq-port 18083 --wallet YOUR_WALLET_ADDRESS --stratum 0.0.0.0:%d --p2p 0.0.0.0:%d\n\n",
|
"%s --host 127.0.0.1 --rpc-port 18081 --zmq-port 18083 --wallet YOUR_WALLET_ADDRESS --stratum 0.0.0.0:%d --p2p 0.0.0.0:%d\n\n",
|
||||||
|
|
|
@ -555,7 +555,7 @@ void P2PServer::load_monerod_peer_list()
|
||||||
{
|
{
|
||||||
const Params& params = m_pool->params();
|
const Params& params = m_pool->params();
|
||||||
|
|
||||||
JSONRPCRequest::call(params.m_host.c_str(), params.m_rpcPort, "/get_peer_list",
|
JSONRPCRequest::call(params.m_host, params.m_rpcPort, "/get_peer_list", params.m_rpcLogin,
|
||||||
[this](const char* data, size_t size)
|
[this](const char* data, size_t size)
|
||||||
{
|
{
|
||||||
#define ERR_STR "/get_peer_list RPC request returned invalid JSON "
|
#define ERR_STR "/get_peer_list RPC request returned invalid JSON "
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include "keccak.h"
|
#include "keccak.h"
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <curl/curl.h>
|
||||||
|
|
||||||
constexpr char log_category_prefix[] = "P2Pool ";
|
constexpr char log_category_prefix[] = "P2Pool ";
|
||||||
constexpr int BLOCK_HEADERS_REQUIRED = 720;
|
constexpr int BLOCK_HEADERS_REQUIRED = 720;
|
||||||
|
@ -88,7 +89,13 @@ p2pool::p2pool(int argc, char* argv[])
|
||||||
LOGWARN(1, "Mining to a stagenet wallet address");
|
LOGWARN(1, "Mining to a stagenet wallet address");
|
||||||
}
|
}
|
||||||
|
|
||||||
int err = uv_async_init(uv_default_loop_checked(), &m_submitBlockAsync, on_submit_block);
|
int err = static_cast<int>(curl_global_init(CURL_GLOBAL_ALL));
|
||||||
|
if (err != CURLE_OK) {
|
||||||
|
LOGERR(1, "Failed to initialize curl, error " << err);
|
||||||
|
throw std::exception();
|
||||||
|
}
|
||||||
|
|
||||||
|
err = uv_async_init(uv_default_loop_checked(), &m_submitBlockAsync, on_submit_block);
|
||||||
if (err) {
|
if (err) {
|
||||||
LOGERR(1, "uv_async_init failed, error " << uv_err_name(err));
|
LOGERR(1, "uv_async_init failed, error " << uv_err_name(err));
|
||||||
throw std::exception();
|
throw std::exception();
|
||||||
|
@ -176,6 +183,8 @@ p2pool::~p2pool()
|
||||||
delete m_mempool;
|
delete m_mempool;
|
||||||
delete m_params;
|
delete m_params;
|
||||||
delete m_consoleCommands;
|
delete m_consoleCommands;
|
||||||
|
|
||||||
|
curl_global_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool p2pool::calculate_hash(const void* data, size_t size, uint64_t height, const hash& seed, hash& result)
|
bool p2pool::calculate_hash(const void* data, size_t size, uint64_t height, const hash& seed, hash& result)
|
||||||
|
@ -311,11 +320,11 @@ void p2pool::handle_miner_data(MinerData& data)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint64_t h : missing_heights) {
|
for (uint64_t h : missing_heights) {
|
||||||
char buf[log::Stream::BUF_SIZE + 1];
|
char buf[log::Stream::BUF_SIZE + 1] = {};
|
||||||
log::Stream s(buf);
|
log::Stream s(buf);
|
||||||
s << "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_block_header_by_height\",\"params\":{\"height\":" << h << "}}\0";
|
s << "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_block_header_by_height\",\"params\":{\"height\":" << h << "}}\0";
|
||||||
|
|
||||||
JSONRPCRequest::call(m_params->m_host.c_str(), m_params->m_rpcPort, buf,
|
JSONRPCRequest::call(m_params->m_host, m_params->m_rpcPort, buf, m_params->m_rpcLogin,
|
||||||
[this, h](const char* data, size_t size)
|
[this, h](const char* data, size_t size)
|
||||||
{
|
{
|
||||||
ChainMain block;
|
ChainMain block;
|
||||||
|
@ -462,7 +471,10 @@ void p2pool::on_stop(uv_async_t* async)
|
||||||
uv_close(reinterpret_cast<uv_handle_t*>(&pool->m_blockTemplateAsync), nullptr);
|
uv_close(reinterpret_cast<uv_handle_t*>(&pool->m_blockTemplateAsync), nullptr);
|
||||||
uv_close(reinterpret_cast<uv_handle_t*>(&pool->m_stopAsync), nullptr);
|
uv_close(reinterpret_cast<uv_handle_t*>(&pool->m_stopAsync), nullptr);
|
||||||
uv_close(reinterpret_cast<uv_handle_t*>(&pool->m_restartZMQAsync), nullptr);
|
uv_close(reinterpret_cast<uv_handle_t*>(&pool->m_restartZMQAsync), nullptr);
|
||||||
uv_stop(uv_default_loop());
|
|
||||||
|
uv_loop_t* loop = uv_default_loop_checked();
|
||||||
|
delete GetLoopUserData(loop, false);
|
||||||
|
uv_stop(loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
void p2pool::submit_block() const
|
void p2pool::submit_block() const
|
||||||
|
@ -522,7 +534,7 @@ void p2pool::submit_block() const
|
||||||
}
|
}
|
||||||
request.append("\"]}");
|
request.append("\"]}");
|
||||||
|
|
||||||
JSONRPCRequest::call(m_params->m_host.c_str(), m_params->m_rpcPort, request.c_str(),
|
JSONRPCRequest::call(m_params->m_host, m_params->m_rpcPort, request, m_params->m_rpcLogin,
|
||||||
[height, diff, template_id, nonce, extra_nonce, is_external](const char* data, size_t size)
|
[height, diff, template_id, nonce, extra_nonce, is_external](const char* data, size_t size)
|
||||||
{
|
{
|
||||||
rapidjson::Document doc;
|
rapidjson::Document doc;
|
||||||
|
@ -617,7 +629,7 @@ void p2pool::download_block_headers(uint64_t current_height)
|
||||||
const uint64_t seed_height = get_seed_height(current_height);
|
const uint64_t seed_height = get_seed_height(current_height);
|
||||||
const uint64_t prev_seed_height = (seed_height > SEEDHASH_EPOCH_BLOCKS) ? (seed_height - SEEDHASH_EPOCH_BLOCKS) : 0;
|
const uint64_t prev_seed_height = (seed_height > SEEDHASH_EPOCH_BLOCKS) ? (seed_height - SEEDHASH_EPOCH_BLOCKS) : 0;
|
||||||
|
|
||||||
char buf[log::Stream::BUF_SIZE + 1];
|
char buf[log::Stream::BUF_SIZE + 1] = {};
|
||||||
log::Stream s(buf);
|
log::Stream s(buf);
|
||||||
|
|
||||||
// First download 2 RandomX seeds
|
// First download 2 RandomX seeds
|
||||||
|
@ -626,7 +638,7 @@ void p2pool::download_block_headers(uint64_t current_height)
|
||||||
s.m_pos = 0;
|
s.m_pos = 0;
|
||||||
s << "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_block_header_by_height\",\"params\":{\"height\":" << height << "}}\0";
|
s << "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_block_header_by_height\",\"params\":{\"height\":" << height << "}}\0";
|
||||||
|
|
||||||
JSONRPCRequest::call(m_params->m_host.c_str(), m_params->m_rpcPort, buf,
|
JSONRPCRequest::call(m_params->m_host, m_params->m_rpcPort, buf, m_params->m_rpcLogin,
|
||||||
[this, prev_seed_height, height](const char* data, size_t size)
|
[this, prev_seed_height, height](const char* data, size_t size)
|
||||||
{
|
{
|
||||||
ChainMain block;
|
ChainMain block;
|
||||||
|
@ -655,7 +667,7 @@ void p2pool::download_block_headers(uint64_t current_height)
|
||||||
s.m_pos = 0;
|
s.m_pos = 0;
|
||||||
s << "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_block_headers_range\",\"params\":{\"start_height\":" << start_height << ",\"end_height\":" << current_height - 1 << "}}\0";
|
s << "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_block_headers_range\",\"params\":{\"start_height\":" << start_height << ",\"end_height\":" << current_height - 1 << "}}\0";
|
||||||
|
|
||||||
JSONRPCRequest::call(m_params->m_host.c_str(), m_params->m_rpcPort, buf,
|
JSONRPCRequest::call(m_params->m_host, m_params->m_rpcPort, buf, m_params->m_rpcLogin,
|
||||||
[this, start_height, current_height](const char* data, size_t size)
|
[this, start_height, current_height](const char* data, size_t size)
|
||||||
{
|
{
|
||||||
if (parse_block_headers_range(data, size) == current_height - start_height) {
|
if (parse_block_headers_range(data, size) == current_height - start_height) {
|
||||||
|
@ -763,7 +775,7 @@ void p2pool::stratum_on_block()
|
||||||
|
|
||||||
void p2pool::get_info()
|
void p2pool::get_info()
|
||||||
{
|
{
|
||||||
JSONRPCRequest::call(m_params->m_host.c_str(), m_params->m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_info\"}",
|
JSONRPCRequest::call(m_params->m_host, m_params->m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_info\"}", m_params->m_rpcLogin,
|
||||||
[this](const char* data, size_t size)
|
[this](const char* data, size_t size)
|
||||||
{
|
{
|
||||||
parse_get_info_rpc(data, size);
|
parse_get_info_rpc(data, size);
|
||||||
|
@ -869,7 +881,7 @@ void p2pool::parse_get_info_rpc(const char* data, size_t size)
|
||||||
|
|
||||||
void p2pool::get_version()
|
void p2pool::get_version()
|
||||||
{
|
{
|
||||||
JSONRPCRequest::call(m_params->m_host.c_str(), m_params->m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_version\"}",
|
JSONRPCRequest::call(m_params->m_host, m_params->m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_version\"}", m_params->m_rpcLogin,
|
||||||
[this](const char* data, size_t size)
|
[this](const char* data, size_t size)
|
||||||
{
|
{
|
||||||
parse_get_version_rpc(data, size);
|
parse_get_version_rpc(data, size);
|
||||||
|
@ -933,7 +945,7 @@ void p2pool::get_miner_data()
|
||||||
{
|
{
|
||||||
m_getMinerDataPending = true;
|
m_getMinerDataPending = true;
|
||||||
|
|
||||||
JSONRPCRequest::call(m_params->m_host.c_str(), m_params->m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_miner_data\"}",
|
JSONRPCRequest::call(m_params->m_host, m_params->m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_miner_data\"}", m_params->m_rpcLogin,
|
||||||
[this](const char* data, size_t size)
|
[this](const char* data, size_t size)
|
||||||
{
|
{
|
||||||
parse_get_miner_data_rpc(data, size);
|
parse_get_miner_data_rpc(data, size);
|
||||||
|
@ -1473,6 +1485,11 @@ int p2pool::run()
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init default loop user data before running it
|
||||||
|
uv_loop_t* loop = uv_default_loop_checked();
|
||||||
|
loop->data = nullptr;
|
||||||
|
GetLoopUserData(loop);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
get_info();
|
get_info();
|
||||||
load_found_blocks();
|
load_found_blocks();
|
||||||
|
|
|
@ -130,6 +130,11 @@ Params::Params(int argc, char* argv[])
|
||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((strcmp(argv[i], "--rpc-login") == 0) && (i + 1 < argc)) {
|
||||||
|
m_rpcLogin = argv[++i];
|
||||||
|
ok = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
fprintf(stderr, "Unknown command line parameter %s\n\n", argv[i]);
|
fprintf(stderr, "Unknown command line parameter %s\n\n", argv[i]);
|
||||||
p2pool_usage();
|
p2pool_usage();
|
||||||
|
|
|
@ -49,6 +49,7 @@ struct Params
|
||||||
uint32_t m_minerThreads = 0;
|
uint32_t m_minerThreads = 0;
|
||||||
bool m_mini = false;
|
bool m_mini = false;
|
||||||
bool m_autoDiff = true;
|
bool m_autoDiff = true;
|
||||||
|
std::string m_rpcLogin;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace p2pool
|
} // namespace p2pool
|
||||||
|
|
|
@ -370,6 +370,7 @@ bool RandomX_Hasher::calculate(const void* data, size_t size, uint64_t /*height*
|
||||||
|
|
||||||
RandomX_Hasher_RPC::RandomX_Hasher_RPC(p2pool* pool)
|
RandomX_Hasher_RPC::RandomX_Hasher_RPC(p2pool* pool)
|
||||||
: m_pool(pool)
|
: m_pool(pool)
|
||||||
|
, m_loop{}
|
||||||
, m_loopThread{}
|
, m_loopThread{}
|
||||||
{
|
{
|
||||||
int err = uv_loop_init(&m_loop);
|
int err = uv_loop_init(&m_loop);
|
||||||
|
@ -378,6 +379,9 @@ RandomX_Hasher_RPC::RandomX_Hasher_RPC(p2pool* pool)
|
||||||
panic();
|
panic();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init loop user data before running it
|
||||||
|
GetLoopUserData(&m_loop);
|
||||||
|
|
||||||
uv_async_init(&m_loop, &m_shutdownAsync, on_shutdown);
|
uv_async_init(&m_loop, &m_shutdownAsync, on_shutdown);
|
||||||
uv_async_init(&m_loop, &m_kickTheLoopAsync, nullptr);
|
uv_async_init(&m_loop, &m_kickTheLoopAsync, nullptr);
|
||||||
m_shutdownAsync.data = this;
|
m_shutdownAsync.data = this;
|
||||||
|
@ -426,17 +430,17 @@ bool RandomX_Hasher_RPC::calculate(const void* data_ptr, size_t size, uint64_t h
|
||||||
const uint8_t* data = reinterpret_cast<const uint8_t*>(data_ptr);
|
const uint8_t* data = reinterpret_cast<const uint8_t*>(data_ptr);
|
||||||
const uint8_t major_version = data[0];
|
const uint8_t major_version = data[0];
|
||||||
|
|
||||||
char buf[log::Stream::BUF_SIZE + 1];
|
char buf[log::Stream::BUF_SIZE + 1] = {};
|
||||||
log::Stream s(buf);
|
log::Stream s(buf);
|
||||||
s << "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"calc_pow\",\"params\":{\"major_version\":" << major_version <<
|
s << "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"calc_pow\",\"params\":{\"major_version\":" << major_version <<
|
||||||
",\"height\":" << height <<
|
",\"height\":" << height <<
|
||||||
",\"block_blob\":\"" << log::hex_buf(data, size) << '"' <<
|
",\"block_blob\":\"" << log::hex_buf(data, size) << '"' <<
|
||||||
",\"seed_hash\":\"\"}}";
|
",\"seed_hash\":\"\"}}\0";
|
||||||
|
|
||||||
volatile int result = 0;
|
volatile int result = 0;
|
||||||
volatile bool done = false;
|
volatile bool done = false;
|
||||||
|
|
||||||
JSONRPCRequest::call(m_pool->params().m_host.c_str(), m_pool->params().m_rpcPort, buf,
|
JSONRPCRequest::call(m_pool->params().m_host, m_pool->params().m_rpcPort, buf, m_pool->params().m_rpcLogin,
|
||||||
[&result, &h](const char* data, size_t size)
|
[&result, &h](const char* data, size_t size)
|
||||||
{
|
{
|
||||||
rapidjson::Document doc;
|
rapidjson::Document doc;
|
||||||
|
|
|
@ -122,6 +122,8 @@ private:
|
||||||
RandomX_Hasher_RPC* server = reinterpret_cast<RandomX_Hasher_RPC*>(async->data);
|
RandomX_Hasher_RPC* server = reinterpret_cast<RandomX_Hasher_RPC*>(async->data);
|
||||||
uv_close(reinterpret_cast<uv_handle_t*>(&server->m_shutdownAsync), nullptr);
|
uv_close(reinterpret_cast<uv_handle_t*>(&server->m_shutdownAsync), nullptr);
|
||||||
uv_close(reinterpret_cast<uv_handle_t*>(&server->m_kickTheLoopAsync), nullptr);
|
uv_close(reinterpret_cast<uv_handle_t*>(&server->m_kickTheLoopAsync), nullptr);
|
||||||
|
|
||||||
|
delete GetLoopUserData(&server->m_loop, false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -177,6 +177,8 @@ protected:
|
||||||
|
|
||||||
uv_close(reinterpret_cast<uv_handle_t*>(&server->m_dropConnectionsAsync), nullptr);
|
uv_close(reinterpret_cast<uv_handle_t*>(&server->m_dropConnectionsAsync), nullptr);
|
||||||
uv_close(reinterpret_cast<uv_handle_t*>(&server->m_shutdownAsync), nullptr);
|
uv_close(reinterpret_cast<uv_handle_t*>(&server->m_shutdownAsync), nullptr);
|
||||||
|
|
||||||
|
delete GetLoopUserData(&server->m_loop, false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ TCPServer<READ_BUF_SIZE, WRITE_BUF_SIZE>::TCPServer(allocate_client_callback all
|
||||||
, m_loopThread{}
|
, m_loopThread{}
|
||||||
, m_finished(0)
|
, m_finished(0)
|
||||||
, m_listenPort(-1)
|
, m_listenPort(-1)
|
||||||
|
, m_loop{}
|
||||||
, m_loopStopped{false}
|
, m_loopStopped{false}
|
||||||
, m_numConnections{ 0 }
|
, m_numConnections{ 0 }
|
||||||
, m_numIncomingConnections{ 0 }
|
, m_numIncomingConnections{ 0 }
|
||||||
|
@ -37,6 +38,9 @@ TCPServer<READ_BUF_SIZE, WRITE_BUF_SIZE>::TCPServer(allocate_client_callback all
|
||||||
panic();
|
panic();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init loop user data before running it
|
||||||
|
GetLoopUserData(&m_loop);
|
||||||
|
|
||||||
err = uv_async_init(&m_loop, &m_dropConnectionsAsync, on_drop_connections);
|
err = uv_async_init(&m_loop, &m_dropConnectionsAsync, on_drop_connections);
|
||||||
if (err) {
|
if (err) {
|
||||||
LOGERR(1, "uv_async_init failed, error " << uv_err_name(err));
|
LOGERR(1, "uv_async_init failed, error " << uv_err_name(err));
|
||||||
|
|
12
src/util.cpp
12
src/util.cpp
|
@ -423,4 +423,16 @@ NOINLINE uint64_t bsr_reference(uint64_t x)
|
||||||
return bsr8_table.data[y >> 24] - n0 - n1 - n2;
|
return bsr8_table.data[y >> 24] - n0 - n1 - n2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UV_LoopUserData* GetLoopUserData(uv_loop_t* loop, bool create)
|
||||||
|
{
|
||||||
|
UV_LoopUserData* data = reinterpret_cast<UV_LoopUserData*>(loop->data);
|
||||||
|
|
||||||
|
if (!data && create) {
|
||||||
|
data = new UV_LoopUserData(loop);
|
||||||
|
loop->data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace p2pool
|
} // namespace p2pool
|
||||||
|
|
|
@ -61,4 +61,93 @@ void uv_mutex_init_checked(uv_mutex_t* mutex);
|
||||||
void uv_rwlock_init_checked(uv_rwlock_t* lock);
|
void uv_rwlock_init_checked(uv_rwlock_t* lock);
|
||||||
uv_loop_t* uv_default_loop_checked();
|
uv_loop_t* uv_default_loop_checked();
|
||||||
|
|
||||||
|
struct UV_LoopCallbackBase
|
||||||
|
{
|
||||||
|
virtual ~UV_LoopCallbackBase() {}
|
||||||
|
virtual void operator()() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct UV_LoopCallback : public UV_LoopCallbackBase
|
||||||
|
{
|
||||||
|
explicit FORCEINLINE UV_LoopCallback(T&& cb) : m_cb(std::move(cb)) {}
|
||||||
|
void operator()() override { m_cb(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
UV_LoopCallback& operator=(UV_LoopCallback&&) = delete;
|
||||||
|
T m_cb;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UV_LoopUserData
|
||||||
|
{
|
||||||
|
uv_loop_t* m_loop;
|
||||||
|
uv_async_t* m_async;
|
||||||
|
|
||||||
|
uv_mutex_t m_callbacksLock;
|
||||||
|
std::vector<UV_LoopCallbackBase*> m_callbacks;
|
||||||
|
|
||||||
|
std::vector<UV_LoopCallbackBase*> m_callbacksToRun;
|
||||||
|
|
||||||
|
explicit UV_LoopUserData(uv_loop_t* loop)
|
||||||
|
: m_loop(loop)
|
||||||
|
, m_async(new uv_async_t{})
|
||||||
|
, m_callbacksLock{}
|
||||||
|
, m_callbacks{}
|
||||||
|
, m_callbacksToRun{}
|
||||||
|
{
|
||||||
|
uv_async_init(m_loop, m_async, async_cb);
|
||||||
|
m_async->data = this;
|
||||||
|
|
||||||
|
uv_mutex_init_checked(&m_callbacksLock);
|
||||||
|
|
||||||
|
m_callbacks.reserve(2);
|
||||||
|
m_callbacksToRun.reserve(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
~UV_LoopUserData()
|
||||||
|
{
|
||||||
|
m_loop->data = nullptr;
|
||||||
|
uv_mutex_destroy(&m_callbacksLock);
|
||||||
|
uv_close(reinterpret_cast<uv_handle_t*>(m_async), [](uv_handle_t* h) { delete reinterpret_cast<uv_async_t*>(h); });
|
||||||
|
for (const UV_LoopCallbackBase* cb : m_callbacks) {
|
||||||
|
delete cb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void async_cb(uv_async_t* h)
|
||||||
|
{
|
||||||
|
UV_LoopUserData* data = reinterpret_cast<UV_LoopUserData*>(h->data);
|
||||||
|
|
||||||
|
data->m_callbacksToRun.clear();
|
||||||
|
{
|
||||||
|
MutexLock lock(data->m_callbacksLock);
|
||||||
|
std::swap(data->m_callbacks, data->m_callbacksToRun);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (UV_LoopCallbackBase* cb : data->m_callbacksToRun) {
|
||||||
|
(*cb)();
|
||||||
|
delete cb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UV_LoopUserData(const UV_LoopUserData&) = delete;
|
||||||
|
UV_LoopUserData& operator=(const UV_LoopUserData&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
UV_LoopUserData* GetLoopUserData(uv_loop_t* loop, bool create = true);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void CallOnLoop(uv_loop_t* loop, T&& callback)
|
||||||
|
{
|
||||||
|
UV_LoopUserData* data = GetLoopUserData(loop);
|
||||||
|
|
||||||
|
UV_LoopCallbackBase* cb = new UV_LoopCallback<T>(std::move(callback));
|
||||||
|
{
|
||||||
|
MutexLock lock(data->m_callbacksLock);
|
||||||
|
data->m_callbacks.push_back(cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
uv_async_send(data->m_async);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace p2pool
|
} // namespace p2pool
|
||||||
|
|
|
@ -32,9 +32,6 @@ set(SOURCES
|
||||||
src/wallet_tests.cpp
|
src/wallet_tests.cpp
|
||||||
../external/src/cryptonote/crypto-ops-data.c
|
../external/src/cryptonote/crypto-ops-data.c
|
||||||
../external/src/cryptonote/crypto-ops.c
|
../external/src/cryptonote/crypto-ops.c
|
||||||
../external/src/llhttp/api.c
|
|
||||||
../external/src/llhttp/http.c
|
|
||||||
../external/src/llhttp/llhttp.c
|
|
||||||
../src/block_cache.cpp
|
../src/block_cache.cpp
|
||||||
../src/block_template.cpp
|
../src/block_template.cpp
|
||||||
../src/console_commands.cpp
|
../src/console_commands.cpp
|
||||||
|
@ -61,10 +58,10 @@ set(SOURCES
|
||||||
include_directories(../src)
|
include_directories(../src)
|
||||||
include_directories(../external/src)
|
include_directories(../external/src)
|
||||||
include_directories(../external/src/cryptonote)
|
include_directories(../external/src/cryptonote)
|
||||||
|
include_directories(../external/src/curl/include)
|
||||||
include_directories(../external/src/libuv/include)
|
include_directories(../external/src/libuv/include)
|
||||||
include_directories(../external/src/cppzmq)
|
include_directories(../external/src/cppzmq)
|
||||||
include_directories(../external/src/libzmq/include)
|
include_directories(../external/src/libzmq/include)
|
||||||
include_directories(../external/src/llhttp)
|
|
||||||
include_directories(../external/src/RandomX/src)
|
include_directories(../external/src/RandomX/src)
|
||||||
include_directories(../external/src/rapidjson/include)
|
include_directories(../external/src/rapidjson/include)
|
||||||
include_directories(../external/src/robin-hood-hashing/src/include)
|
include_directories(../external/src/robin-hood-hashing/src/include)
|
||||||
|
@ -72,7 +69,8 @@ include_directories(src)
|
||||||
include_directories(googletest/googletest/include)
|
include_directories(googletest/googletest/include)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
set(LIBS ${LIBS} ws2_32 iphlpapi userenv psapi)
|
set(LIBS ${LIBS} ws2_32 iphlpapi userenv psapi wldap32)
|
||||||
|
add_definitions(-DCURL_STATICLIB)
|
||||||
elseif (NOT APPLE)
|
elseif (NOT APPLE)
|
||||||
set(LIBS ${LIBS} pthread gss dl)
|
set(LIBS ${LIBS} pthread gss dl)
|
||||||
endif()
|
endif()
|
||||||
|
@ -82,17 +80,28 @@ if (STATIC_LIBS)
|
||||||
set(ZMQ_LIBRARY_DEBUG "${CMAKE_SOURCE_DIR}/../external/src/libzmq/build/lib/libzmq.a")
|
set(ZMQ_LIBRARY_DEBUG "${CMAKE_SOURCE_DIR}/../external/src/libzmq/build/lib/libzmq.a")
|
||||||
set(UV_LIBRARY_DEBUG "${CMAKE_SOURCE_DIR}/../external/src/libuv/build/libuv_a.a")
|
set(UV_LIBRARY_DEBUG "${CMAKE_SOURCE_DIR}/../external/src/libuv/build/libuv_a.a")
|
||||||
set(UV_LIBRARY "${CMAKE_SOURCE_DIR}/../external/src/libuv/build/libuv_a.a")
|
set(UV_LIBRARY "${CMAKE_SOURCE_DIR}/../external/src/libuv/build/libuv_a.a")
|
||||||
|
set(CURL_LIBRARY_DEBUG "${CMAKE_SOURCE_DIR}/../external/src/curl/lib/.libs/libcurl.a")
|
||||||
|
set(CURL_LIBRARY "${CMAKE_SOURCE_DIR}/../external/src/curl/lib/.libs/libcurl.a")
|
||||||
else()
|
else()
|
||||||
if (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
if (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||||
find_library(ZMQ_LIBRARY_DEBUG NAMES libzmq-v142-mt-sgd-4_3_5 PATHS "../external/lib/libzmq/Debug")
|
find_library(ZMQ_LIBRARY_DEBUG NAMES libzmq-v142-mt-sgd-4_3_5 PATHS "../external/lib/libzmq/Debug")
|
||||||
find_library(ZMQ_LIBRARY NAMES libzmq-v142-mt-s-4_3_5 PATHS "../external/lib/libzmq/Release")
|
find_library(ZMQ_LIBRARY NAMES libzmq-v142-mt-s-4_3_5 PATHS "../external/lib/libzmq/Release")
|
||||||
find_library(UV_LIBRARY_DEBUG NAMES uv_a PATHS "../external/lib/libuv/Debug")
|
find_library(UV_LIBRARY_DEBUG NAMES uv_a PATHS "../external/lib/libuv/Debug")
|
||||||
find_library(UV_LIBRARY NAMES uv_a PATHS "../external/lib/libuv/Release")
|
find_library(UV_LIBRARY NAMES uv_a PATHS "../external/lib/libuv/Release")
|
||||||
|
find_library(CURL_LIBRARY_DEBUG NAMES libcurld PATHS "../external/lib/libcurl/Debug")
|
||||||
|
find_library(CURL_LIBRARY NAMES libcurl PATHS "../external/lib/libcurl/Release")
|
||||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES GNU OR CMAKE_CXX_COMPILER_ID MATCHES Clang)
|
elseif (CMAKE_CXX_COMPILER_ID MATCHES GNU OR CMAKE_CXX_COMPILER_ID MATCHES Clang)
|
||||||
find_library(ZMQ_LIBRARY_DEBUG NAMES zmq libzmq.a)
|
find_library(ZMQ_LIBRARY_DEBUG NAMES zmq libzmq.a)
|
||||||
find_library(ZMQ_LIBRARY NAMES zmq libzmq.a)
|
find_library(ZMQ_LIBRARY NAMES zmq libzmq.a)
|
||||||
find_library(UV_LIBRARY_DEBUG NAMES uv libuv.a)
|
find_library(UV_LIBRARY_DEBUG NAMES uv libuv.a)
|
||||||
find_library(UV_LIBRARY NAMES uv libuv.a)
|
find_library(UV_LIBRARY NAMES uv libuv.a)
|
||||||
|
if (WIN32)
|
||||||
|
find_library(CURL_LIBRARY_DEBUG NAMES libcurl.a PATHS "../external/src/curl/lib/.libs" NO_DEFAULT_PATH)
|
||||||
|
find_library(CURL_LIBRARY NAMES libcurl.a PATHS "../external/src/curl/lib/.libs" NO_DEFAULT_PATH)
|
||||||
|
else()
|
||||||
|
find_library(CURL_LIBRARY_DEBUG NAMES curl)
|
||||||
|
find_library(CURL_LIBRARY NAMES curl)
|
||||||
|
endif()
|
||||||
find_library(SODIUM_LIBRARY sodium)
|
find_library(SODIUM_LIBRARY sodium)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -112,6 +121,13 @@ if (NORM_LIBRARY)
|
||||||
set(LIBS ${LIBS} ${NORM_LIBRARY})
|
set(LIBS ${LIBS} ${NORM_LIBRARY})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(APPLE)
|
||||||
|
find_library(FOUNDATION_LIB Foundation)
|
||||||
|
find_library(CORE_FOUNDATION_LIB CoreFoundation)
|
||||||
|
find_library(SYSTEM_CONFIGURATION_LIB SystemConfiguration)
|
||||||
|
set(LIBS ${LIBS} ${FOUNDATION_LIB} ${CORE_FOUNDATION_LIB} ${SYSTEM_CONFIGURATION_LIB})
|
||||||
|
endif()
|
||||||
|
|
||||||
add_definitions(/DZMQ_STATIC /DP2POOL_LOG_DISABLE)
|
add_definitions(/DZMQ_STATIC /DP2POOL_LOG_DISABLE)
|
||||||
|
|
||||||
include(CheckCXXSourceCompiles)
|
include(CheckCXXSourceCompiles)
|
||||||
|
@ -128,7 +144,7 @@ if (HAVE_BITSCANREVERSE64)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES})
|
add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES})
|
||||||
target_link_libraries(${CMAKE_PROJECT_NAME} debug ${ZMQ_LIBRARY_DEBUG} debug ${UV_LIBRARY_DEBUG} optimized ${ZMQ_LIBRARY} optimized ${UV_LIBRARY} ${LIBS})
|
target_link_libraries(${CMAKE_PROJECT_NAME} debug ${ZMQ_LIBRARY_DEBUG} debug ${UV_LIBRARY_DEBUG} debug ${CURL_LIBRARY_DEBUG} optimized ${ZMQ_LIBRARY} optimized ${UV_LIBRARY} optimized ${CURL_LIBRARY} ${LIBS})
|
||||||
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/src/crypto_tests.txt" $<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>)
|
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/src/crypto_tests.txt" $<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>)
|
||||||
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/src/mainnet_test2_block.dat" $<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>)
|
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/src/mainnet_test2_block.dat" $<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>)
|
||||||
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/src/sidechain_dump.dat" $<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>)
|
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/src/sidechain_dump.dat" $<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>)
|
||||||
|
|
Loading…
Reference in a new issue